home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / palette.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-01-15  |  82.5 KB  |  3,272 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #ifdef HAVE_DIRENT_H
  28. #include <sys/types.h>
  29. #include <dirent.h>
  30. #endif
  31. #include <sys/stat.h>
  32. #include <sys/types.h>
  33.  
  34. #include <gtk/gtk.h>
  35.  
  36. #include "apptypes.h"
  37.  
  38. #include "appenv.h"
  39. #include "color_area.h"
  40. #include "color_notebook.h"
  41. #include "datafiles.h"
  42. #include "gimpcontext.h"
  43. #include "gimpdnd.h"
  44. #include "gimprc.h"
  45. #include "gimpui.h"
  46. #include "gradient_header.h"
  47. #include "gradient_select.h"
  48. #include "palette.h"
  49. #include "paletteP.h"
  50. #include "palette_entries.h"
  51. #include "session.h"
  52. #include "palette_select.h"
  53. #include "dialog_handler.h"
  54.  
  55. #include "libgimp/gimpenv.h"
  56.  
  57. #include "libgimp/gimpintl.h"
  58.  
  59. #include "pixmaps/zoom_in.xpm"
  60. #include "pixmaps/zoom_out.xpm"
  61.  
  62. #define ENTRY_WIDTH  12
  63. #define ENTRY_HEIGHT 10
  64. #define SPACING       1
  65. #define COLUMNS      16
  66. #define ROWS         11
  67.  
  68. #define PREVIEW_WIDTH  ((ENTRY_WIDTH * COLUMNS) + (SPACING * (COLUMNS + 1)))
  69. #define PREVIEW_HEIGHT ((ENTRY_HEIGHT * ROWS) + (SPACING * (ROWS + 1)))
  70.  
  71. #define PALETTE_EVENT_MASK GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | \
  72.                            GDK_ENTER_NOTIFY_MASK
  73.  
  74. /* New palette code... */
  75.  
  76. #define IMPORT_PREVIEW_WIDTH  80
  77. #define IMPORT_PREVIEW_HEIGHT 80
  78. #define MAX_IMAGE_COLORS      (10000*2)
  79.  
  80. typedef enum
  81. {
  82.   GRAD_IMPORT = 0,
  83.   IMAGE_IMPORT = 1,
  84.   INDEXED_IMPORT = 2
  85. } ImportType;
  86.  
  87. typedef struct _ImportDialog ImportDialog;
  88.  
  89. struct _ImportDialog
  90. {
  91.   GtkWidget     *dialog;
  92.   GtkWidget     *preview;
  93.   GtkWidget     *entry;
  94.   GtkWidget     *select_area;
  95.   GtkWidget     *select;
  96.   GtkWidget     *image_list;
  97.   GtkWidget     *image_menu_item_image;
  98.   GtkWidget     *image_menu_item_indexed;
  99.   GtkWidget     *image_menu_item_gradient;
  100.   GtkWidget     *optionmenu1_menu;
  101.   GtkWidget     *type_option;
  102.   GtkWidget     *threshold_scale;
  103.   GtkWidget     *threshold_text;
  104.   GtkAdjustment *threshold;
  105.   GtkAdjustment *sample;
  106.   ImportType     import_type;
  107.   GimpImage     *gimage;
  108. };
  109.  
  110. typedef struct _PaletteDialog PaletteDialog;
  111.  
  112. struct _PaletteDialog
  113. {
  114.   GtkWidget      *shell;
  115.  
  116.   GtkWidget      *color_area;
  117.   GtkWidget      *scrolled_window;
  118.   GtkWidget      *color_name;
  119.   GtkWidget      *clist;
  120.  
  121.   GtkWidget      *popup_menu;
  122.   GtkWidget      *delete_menu_item;
  123.   GtkWidget      *edit_menu_item;
  124.  
  125.   ColorNotebook  *color_notebook;
  126.   gboolean        color_notebook_active;
  127.  
  128.   PaletteEntries *entries;
  129.   PaletteEntry   *color;
  130.   PaletteEntry   *dnd_color;
  131.  
  132.   GdkGC          *gc;
  133.   guint           entry_sig_id;
  134.   gfloat          zoom_factor;  /* range from 0.1 to 4.0 */
  135.   gint            col_width;
  136.   gint            last_width;
  137.   gint            columns;
  138.   gboolean        freeze_update;
  139.   gboolean        columns_valid;
  140. };
  141.  
  142. /*  local function prototypes  */
  143. static void  palette_entry_free    (PaletteEntry *);
  144. static void  palette_entries_free  (PaletteEntries *);
  145. static void  palette_entries_load  (gchar *);
  146. static void  palette_entries_save  (PaletteEntries *, gchar *);
  147. static void  palette_save_palettes (void);
  148.  
  149. static void  palette_entries_list_insert    (PaletteEntries *entries);
  150.  
  151. static void  palette_dialog_draw_entries    (PaletteDialog *palette,
  152.                          gint           row_start,
  153.                          gint           column_highlight);
  154. static void  palette_dialog_redraw          (PaletteDialog *palette);
  155. static void  palette_dialog_scroll_top_left (PaletteDialog *palette);
  156.  
  157. static PaletteDialog * palette_dialog_new        (gboolean       editor);
  158. static ImportDialog  * palette_import_dialog_new (PaletteDialog *palette);
  159.  
  160.  
  161. GSList                *palette_entries_list    = NULL;
  162. PaletteDialog         *top_level_edit_palette  = NULL;
  163. PaletteDialog         *top_level_palette       = NULL;
  164.  
  165. static PaletteEntries *default_palette_entries = NULL;
  166. static gint            num_palette_entries     = 0;
  167. static ImportDialog   *import_dialog           = NULL;
  168.  
  169.  
  170. /*  dnd stuff  */
  171. static GtkTargetEntry color_palette_target_table[] =
  172. {
  173.   GIMP_TARGET_COLOR
  174. };
  175. static guint n_color_palette_targets = (sizeof (color_palette_target_table) /
  176.                     sizeof (color_palette_target_table[0]));
  177.  
  178. /*  public functions  ********************************************************/
  179.  
  180. void
  181. palettes_init (gboolean no_data)
  182. {
  183.   if (!no_data)
  184.     datafiles_read_directories (palette_path, palette_entries_load, 0);
  185.  
  186.   if (!default_palette_entries && palette_entries_list)
  187.     default_palette_entries = palette_entries_list->data;
  188. }
  189.  
  190. void
  191. palettes_free (void)
  192. {
  193.   PaletteEntries *entries;
  194.   GSList *list;
  195.  
  196.   for (list = palette_entries_list; list; list = g_slist_next (list))
  197.     {
  198.       entries = (PaletteEntries *) list->data;
  199.  
  200.       /*  If the palette has been changed, save it, if possible  */
  201.       if (entries->changed)
  202.     /*  save the palette  */
  203.     palette_entries_save (entries, entries->filename);
  204.  
  205.       palette_entries_free (entries);
  206.     }
  207.  
  208.   g_slist_free (palette_entries_list);
  209.  
  210.   num_palette_entries = 0;
  211.   palette_entries_list = NULL;
  212. }
  213.  
  214. void 
  215. palette_dialog_create (void)
  216. {
  217.   if (top_level_palette == NULL)
  218.     {
  219.       top_level_palette = palette_dialog_new (TRUE);
  220.       session_set_window_geometry (top_level_palette->shell,
  221.                    &palette_session_info, TRUE);
  222.       dialog_register (top_level_palette->shell);
  223.  
  224.       gtk_widget_show (top_level_palette->shell);
  225.     }
  226.   else
  227.     {
  228.       if (! GTK_WIDGET_VISIBLE (top_level_palette->shell))
  229.     {
  230.       gtk_widget_show (top_level_palette->shell);
  231.     }
  232.       else
  233.     {
  234.       gdk_window_raise (top_level_palette->shell->window);
  235.     }
  236.     }
  237. }
  238.  
  239. void
  240. palette_dialog_free (void)
  241. {
  242.   if (top_level_edit_palette) 
  243.     {
  244.       if (import_dialog)
  245.     {
  246.       gtk_widget_destroy (import_dialog->dialog);
  247.       g_free (import_dialog);
  248.       import_dialog = NULL;
  249.     }
  250.  
  251.       gdk_gc_destroy (top_level_edit_palette->gc); 
  252.       
  253.       if (top_level_edit_palette->color_notebook) 
  254.     color_notebook_free (top_level_edit_palette->color_notebook); 
  255.  
  256.       g_free (top_level_edit_palette); 
  257.       top_level_edit_palette = NULL; 
  258.     }
  259.  
  260.   if (top_level_palette)
  261.     {
  262.       gdk_gc_destroy (top_level_palette->gc); 
  263.       session_get_window_info (top_level_palette->shell,
  264.                    &palette_session_info);  
  265.  
  266.       if (top_level_palette->color_notebook) 
  267.     color_notebook_free (top_level_palette->color_notebook); 
  268.  
  269.       g_free (top_level_palette);
  270.       top_level_palette = NULL;
  271.     }
  272. }
  273.  
  274. /*  palette entries functions  ***********************************************/
  275.  
  276. static PaletteEntries *
  277. palette_entries_new (gchar *palette_name)
  278. {
  279.   PaletteEntries *entries = NULL;
  280.   GList *pal_path;
  281.   gchar *pal_dir;
  282.  
  283.   if (!palette_name || !palette_path)
  284.     return NULL;
  285.  
  286.   pal_path = gimp_path_parse (palette_path, 16, TRUE, NULL);
  287.   pal_dir  = gimp_path_get_user_writable_dir (pal_path);
  288.   gimp_path_free (pal_path);
  289.  
  290.   entries = g_new (PaletteEntries, 1);
  291.  
  292.   if (pal_dir)
  293.     {
  294.       entries->filename = g_strdup_printf ("%s%s", pal_dir, palette_name);
  295.       g_free (pal_dir);
  296.     }
  297.   else
  298.     {
  299.       entries->filename = NULL;
  300.     }
  301.  
  302.   entries->name     = palette_name;  /*  this memory is ours  */
  303.   entries->colors   = NULL;
  304.   entries->n_colors = 0;
  305.   entries->changed  = TRUE;
  306.   entries->pixmap   = NULL;
  307.  
  308.   palette_entries_list_insert (entries);
  309.  
  310.   palette_save_palettes ();
  311.  
  312.   return entries;
  313. }
  314.  
  315. static void
  316. palette_entries_free (PaletteEntries *entries)
  317. {
  318.   PaletteEntry *entry;
  319.   GSList *list;
  320.  
  321.   for (list = entries->colors; list; list = g_slist_next (list))
  322.     {
  323.       entry = (PaletteEntry *) list->data;
  324.  
  325.       palette_entry_free (entry);
  326.     }
  327.  
  328.   g_slist_free (entries->colors);
  329.  
  330.   if (entries->name)
  331.     g_free (entries->name);
  332.  
  333.   if (entries->filename)
  334.     g_free (entries->filename);
  335.  
  336.   if (entries->pixmap)
  337.     gdk_pixmap_unref (entries->pixmap);
  338.  
  339.   g_free (entries);
  340. }
  341.  
  342. static PaletteEntry *
  343. palette_entries_add_entry (PaletteEntries *entries,
  344.                gchar          *name,
  345.                gint            r,
  346.                gint            g,
  347.                gint            b)
  348. {
  349.   PaletteEntry *entry;
  350.  
  351.   if (entries)
  352.     {
  353.       entry = g_new (PaletteEntry, 1);
  354.  
  355.       entry->color[0] = r;
  356.       entry->color[1] = g;
  357.       entry->color[2] = b;
  358.       entry->name     = g_strdup (name ? name : _("Untitled"));
  359.       entry->position = entries->n_colors;
  360.  
  361.       entries->colors    = g_slist_append (entries->colors, entry);
  362.       entries->n_colors += 1;
  363.       entries->changed   = TRUE;
  364.       
  365.       return entry;
  366.     }
  367.  
  368.   return NULL;
  369. }
  370.  
  371. static void
  372. palette_entries_load (gchar *filename)
  373. {
  374.   PaletteEntries *entries;
  375.   gchar  str[512];
  376.   gchar *tok;
  377.   FILE  *fp;
  378.   gint   r, g, b;
  379.   gint   linenum;
  380.  
  381.   r = g = b = 0;
  382.  
  383.   entries = g_new (PaletteEntries, 1);
  384.  
  385.   entries->filename = g_strdup (filename);
  386.   entries->name     = g_strdup (g_basename (filename));
  387.   entries->colors   = NULL;
  388.   entries->n_colors = 0;
  389.   entries->pixmap   = NULL;
  390.  
  391.   /*  Open the requested file  */
  392.   if (! (fp = fopen (filename, "r")))
  393.     {
  394.       palette_entries_free (entries);
  395.       g_warning ("Failed to open palette file %s: can't happen?", filename);
  396.       return;
  397.     }
  398.  
  399.   linenum = 0;
  400.  
  401.   fread (str, 13, 1, fp);
  402.   str[13] = '\0';
  403.   linenum++;
  404.   if (strcmp (str, "GIMP Palette\n"))
  405.     {
  406.       /* bad magic, but maybe it has \r\n at the end of lines? */
  407.       if (!strcmp (str, "GIMP Palette\r"))
  408.     g_message (_("Loading palette %s:\n"
  409.              "Corrupt palette:\n"
  410.              "missing magic header\n"
  411.              "Does this file need converting from DOS?"), filename);
  412.       else
  413.     g_message (_("Loading palette %s:\n"
  414.              "Corrupt palette: missing magic header"), filename);
  415.       fclose (fp);
  416.       palette_entries_free (entries);
  417.       return;
  418.     }
  419.  
  420.   while (!feof (fp))
  421.     {
  422.       if (!fgets (str, 512, fp))
  423.     {
  424.       if (feof (fp))
  425.         break;
  426.       g_message (_("Loading palette %s (line %d):\nRead error"),
  427.              filename, linenum);
  428.       fclose (fp);
  429.       palette_entries_free (entries);
  430.       return;
  431.     }
  432.  
  433.       linenum++;
  434.  
  435.       if (str[0] != '#')
  436.     {
  437.       tok = strtok (str, " \t");
  438.       if (tok)
  439.         r = atoi (tok);
  440.       else
  441.         /* maybe we should just abort? */
  442.         g_message (_("Loading palette %s (line %d):\n"
  443.              "Missing RED component"), filename, linenum);
  444.  
  445.       tok = strtok (NULL, " \t");
  446.       if (tok)
  447.         g = atoi (tok);
  448.       else
  449.         g_message (_("Loading palette %s (line %d):\n"
  450.              "Missing GREEN component"), filename, linenum);
  451.       
  452.       tok = strtok (NULL, " \t");
  453.       if (tok)
  454.         b = atoi (tok);
  455.       else
  456.         g_message (_("Loading palette %s (line %d):\n"
  457.              "Missing BLUE component"), filename, linenum);
  458.  
  459.       /* optional name */
  460.       tok = strtok (NULL, "\n");
  461.  
  462.       if (r < 0 || r > 255 ||
  463.           g < 0 || g > 255 ||
  464.           b < 0 || b > 255)
  465.         g_message (_("Loading palette %s (line %d):\n"
  466.              "RGB value out of range"), filename, linenum);
  467.  
  468.       palette_entries_add_entry (entries, tok, r, g, b);
  469.     }
  470.     }
  471.  
  472.   /*  Clean up  */
  473.   fclose (fp);
  474.   entries->changed = FALSE;
  475.  
  476.   palette_entries_list_insert (entries);
  477.  
  478.   /*  Check if the current palette is the default one  */
  479.   if (default_palette && 
  480.       strcmp (default_palette, g_basename (filename)) == 0)
  481.     default_palette_entries = entries;
  482. }
  483.  
  484. static void
  485. palette_entry_free (PaletteEntry *entry)
  486. {
  487.   if (entry->name)
  488.     g_free (entry->name);
  489.  
  490.   g_free (entry);
  491. }
  492.  
  493. static void
  494. palette_entries_delete (gchar *filename)
  495. {
  496.   if (filename)
  497.     unlink (filename);
  498. }
  499.  
  500. static void
  501. palette_entries_save (PaletteEntries *palette,
  502.               gchar          *filename)
  503. {
  504.   PaletteEntry *entry;
  505.   GSList *list;
  506.   FILE *fp;
  507.  
  508.   if (! filename)
  509.     return;
  510.  
  511.   /*  Open the requested file  */
  512.   if (! (fp = fopen (filename, "w")))
  513.     {
  514.       g_message (_("Can't save palette \"%s\"\n"), filename);
  515.       return;
  516.     }
  517.  
  518.   fprintf (fp, "GIMP Palette\n");
  519.   fprintf (fp, "# %s -- GIMP Palette file\n", palette->name);
  520.  
  521.   for (list = palette->colors; list; list = g_slist_next (list))
  522.     {
  523.       entry = (PaletteEntry *) list->data;
  524.  
  525.       fprintf (fp, "%d %d %d\t%s\n",
  526.            entry->color[0], entry->color[1], entry->color[2], entry->name);
  527.     }
  528.  
  529.   /*  Clean up  */
  530.   fclose (fp);
  531. }
  532.  
  533. static void
  534. palette_save_palettes (void)
  535. {
  536.   PaletteEntries *entries;
  537.   GSList *list;
  538.  
  539.   for (list = palette_entries_list; list; list = g_slist_next (list))
  540.     {
  541.       entries = (PaletteEntries *) list->data;
  542.  
  543.       /*  If the palette has been changed, save it, if possible  */
  544.       if (entries->changed)
  545.     /*  save the palette  */
  546.     palette_entries_save (entries, entries->filename);
  547.     }
  548. }
  549.  
  550. static void 
  551. palette_entries_update_small_preview (PaletteEntries *entries,
  552.                       GdkGC          *gc)
  553. {
  554.   guchar rgb_buf[SM_PREVIEW_WIDTH * SM_PREVIEW_HEIGHT * 3];
  555.   GSList *list;
  556.   gint index;
  557.   PaletteEntry *entry;
  558.  
  559.   memset (rgb_buf, 0x0, sizeof (rgb_buf));
  560.  
  561.   gdk_draw_rgb_image (entries->pixmap,
  562.               gc,
  563.               0,
  564.               0,
  565.               SM_PREVIEW_WIDTH,
  566.               SM_PREVIEW_HEIGHT,
  567.               GDK_RGB_DITHER_NORMAL,
  568.               rgb_buf,
  569.               SM_PREVIEW_WIDTH*3);
  570.  
  571.   index = 0;
  572.   for (list = entries->colors; list; list = g_slist_next (list))
  573.     {
  574.       guchar cell[3*3*3];
  575.       gint loop;
  576.  
  577.       entry = list->data;
  578.  
  579.       for (loop = 0; loop < 27 ; loop+=3)
  580.     {
  581.       cell[0+loop] = entry->color[0];
  582.       cell[1+loop] = entry->color[1];
  583.       cell[2+loop] = entry->color[2];
  584.     }
  585.  
  586.       gdk_draw_rgb_image (entries->pixmap,
  587.               gc,
  588.               1 + (index % ((SM_PREVIEW_WIDTH-2) / 3)) * 3,
  589.               1 + (index / ((SM_PREVIEW_WIDTH-2) / 3)) * 3,
  590.               3,
  591.               3,
  592.               GDK_RGB_DITHER_NORMAL,
  593.               cell,
  594.               3);
  595.  
  596.       index++;
  597.  
  598.       if (index >= (((SM_PREVIEW_WIDTH-2) * (SM_PREVIEW_HEIGHT-2)) / 9))
  599.     break;
  600.     }
  601. }
  602.  
  603. static void
  604. palette_entries_list_insert (PaletteEntries *entries)
  605. {
  606.   PaletteEntries *p_entries;
  607.   GSList *list;
  608.   gint    pos = 0;
  609.  
  610.   for (list = palette_entries_list; list; list = g_slist_next (list))
  611.     {
  612.       p_entries = (PaletteEntries *) list->data;
  613.       
  614.       /*  to make sure we get something!  */
  615.       if (p_entries == NULL)
  616.     p_entries = default_palette_entries;
  617.  
  618.       if (strcmp (p_entries->name, entries->name) > 0)
  619.     break;
  620.  
  621.       pos++;
  622.     }
  623.  
  624.   /*  add it to the list  */
  625.   num_palette_entries++;
  626.   palette_entries_list = g_slist_insert (palette_entries_list,
  627.                      (gpointer) entries, pos);
  628. }
  629.  
  630. /*  general palette clist update functions  **********************************/
  631.  
  632. void
  633. palette_clist_init (GtkWidget *clist, 
  634.             GtkWidget *shell,
  635.             GdkGC     *gc)
  636. {
  637.   PaletteEntries *p_entries = NULL;
  638.   GSList *list;
  639.   gint pos;
  640.  
  641.   pos = 0;
  642.   for (list = palette_entries_list; list; list = g_slist_next (list))
  643.     {
  644.       p_entries = (PaletteEntries *) list->data;
  645.  
  646.       /*  to make sure we get something!  */
  647.       if (p_entries == NULL)
  648.     p_entries = default_palette_entries;
  649.  
  650.       palette_clist_insert (clist, shell, gc, p_entries, pos);
  651.  
  652.       pos++;
  653.     }
  654. }
  655.  
  656. void
  657. palette_clist_insert (GtkWidget      *clist, 
  658.               GtkWidget      *shell,
  659.               GdkGC          *gc,
  660.               PaletteEntries *entries,
  661.               gint            pos)
  662. {
  663.   gchar *string[3];
  664.  
  665.   string[0] = NULL;
  666.   string[1] = g_strdup_printf ("%d", entries->n_colors);
  667.   string[2] = entries->name;
  668.  
  669.   gtk_clist_insert (GTK_CLIST (clist), pos, string);
  670.  
  671.   g_free (string[1]);
  672.  
  673.   if (entries->pixmap == NULL)
  674.     {
  675.       entries->pixmap = gdk_pixmap_new (shell->window,
  676.                     SM_PREVIEW_WIDTH, 
  677.                     SM_PREVIEW_HEIGHT, 
  678.                     gtk_widget_get_visual (shell)->depth);
  679.       palette_entries_update_small_preview (entries, gc);
  680.     }
  681.  
  682.   gtk_clist_set_pixmap (GTK_CLIST (clist), pos, 0, entries->pixmap, NULL);
  683.   gtk_clist_set_row_data (GTK_CLIST (clist), pos, (gpointer) entries);
  684. }  
  685.  
  686. /*  palette dialog clist update functions  ***********************************/
  687.  
  688. static void
  689. palette_dialog_clist_insert (PaletteDialog  *palette,
  690.                  PaletteEntries *entries)
  691. {
  692.   PaletteEntries *chk_entries;
  693.   GSList *list;
  694.   gint pos;
  695.  
  696.   pos = 0;
  697.   for (list = palette_entries_list; list; list = g_slist_next (list))
  698.     {
  699.       chk_entries = (PaletteEntries *) list->data;
  700.       
  701.       /*  to make sure we get something!  */
  702.       if (chk_entries == NULL)
  703.     return;
  704.  
  705.       if (strcmp (entries->name, chk_entries->name) == 0)
  706.     break;
  707.  
  708.       pos++;
  709.     }
  710.  
  711.   gtk_clist_freeze (GTK_CLIST (palette->clist));
  712.   palette_clist_insert (palette->clist, palette->shell, palette->gc,
  713.             entries, pos);
  714.   gtk_clist_thaw (GTK_CLIST (palette->clist));
  715. }
  716.  
  717. static void
  718. palette_dialog_clist_set_text (PaletteDialog  *palette,
  719.                    PaletteEntries *entries)
  720. {
  721.   PaletteEntries *chk_entries = NULL;
  722.   GSList *list;
  723.   gchar *num_buf;
  724.   gint pos;
  725.  
  726.   pos = 0;
  727.   for (list = palette_entries_list; list; list = g_slist_next (list))
  728.     {
  729.       chk_entries = (PaletteEntries *) list->data;
  730.       
  731.       if (entries == chk_entries)
  732.     break;
  733.  
  734.       pos++;
  735.     }
  736.  
  737.   if (chk_entries == NULL)
  738.     return; /* This is actually and error */
  739.  
  740.   num_buf = g_strdup_printf ("%d", entries->n_colors);;
  741.  
  742.   gtk_clist_set_text (GTK_CLIST (palette->clist), pos, 1, num_buf);
  743.  
  744.   g_free (num_buf);
  745. }
  746.  
  747. static void
  748. palette_dialog_clist_refresh (PaletteDialog *palette)
  749. {
  750.   gtk_clist_freeze (GTK_CLIST (palette->clist));
  751.   gtk_clist_clear (GTK_CLIST (palette->clist));
  752.   palette_clist_init (palette->clist, palette->shell, palette->gc);
  753.   gtk_clist_thaw (GTK_CLIST (palette->clist));
  754.  
  755.   palette->entries = palette_entries_list->data;
  756. }
  757.  
  758. static void 
  759. palette_dialog_clist_scroll_to_current (PaletteDialog *palette)
  760. {
  761.   PaletteEntries *p_entries;
  762.   GSList *list;
  763.   gint pos;
  764.  
  765.   if (palette && palette->entries)
  766.     {
  767.       pos = 0;
  768.       for (list = palette_entries_list; list; list = g_slist_next (list))
  769.     {
  770.       p_entries = (PaletteEntries *) list->data;
  771.       
  772.       if (p_entries == palette->entries)
  773.         break;
  774.  
  775.       pos++;
  776.     }
  777.  
  778.       gtk_clist_unselect_all (GTK_CLIST (palette->clist));
  779.       gtk_clist_select_row (GTK_CLIST (palette->clist), pos, -1);
  780.       gtk_clist_moveto (GTK_CLIST (palette->clist), pos, 0, 0.0, 0.0); 
  781.     }
  782. }
  783.  
  784. /*  update functions for all palette dialogs  ********************************/
  785.  
  786. static void
  787. palette_insert_all (PaletteEntries *entries)
  788. {
  789.   PaletteDialog *palette;
  790.  
  791.   if ((palette = top_level_palette))
  792.     {
  793.       palette_dialog_clist_insert (palette, entries);
  794.  
  795.       if (palette->entries == NULL)
  796.     {
  797.       palette->entries = entries;
  798.       palette_dialog_redraw (palette);
  799.     }
  800.     }
  801.  
  802.   if ((palette = top_level_edit_palette))
  803.     {
  804.       palette_dialog_clist_insert (palette, entries);
  805.  
  806.       palette->entries = entries;
  807.       palette_dialog_redraw (palette);
  808.  
  809.       palette_dialog_clist_scroll_to_current (palette);
  810.     }
  811.  
  812.   /*  Update other selectors on screen  */
  813.   palette_select_clist_insert_all (entries);
  814. }
  815.  
  816. static void
  817. palette_update_all (PaletteEntries *entries)
  818. {
  819.   PaletteDialog *palette;
  820.   GdkGC *gc = NULL;
  821.  
  822.   if (top_level_palette)
  823.     gc = top_level_palette->gc;
  824.   else if (top_level_edit_palette)
  825.     gc = top_level_edit_palette->gc;
  826.  
  827.   if (gc)
  828.     palette_entries_update_small_preview (entries, gc);
  829.  
  830.   if ((palette = top_level_palette))
  831.     {
  832.       if (palette->entries == entries)
  833.     {
  834.       palette->columns_valid = FALSE;
  835.       palette_dialog_redraw (palette);
  836.     }
  837.       palette_dialog_clist_set_text (palette, entries);
  838.     }
  839.  
  840.   if ((palette = top_level_edit_palette))
  841.     {
  842.       if (palette->entries == entries)
  843.     {
  844.       palette->columns_valid = FALSE;
  845.       palette_dialog_redraw (palette);
  846.       palette_dialog_clist_scroll_to_current (palette);
  847.     }
  848.       palette_dialog_clist_set_text (palette, entries);
  849.     }
  850.  
  851.   /*  Update other selectors on screen  */
  852.   palette_select_set_text_all (entries);
  853. }
  854.  
  855. static void
  856. palette_draw_all (PaletteEntries *entries,
  857.           PaletteEntry   *color)
  858. {
  859.   PaletteDialog *palette;
  860.   GdkGC *gc = NULL;
  861.  
  862.   if (top_level_palette)
  863.     gc = top_level_palette->gc;
  864.   else if (top_level_edit_palette)
  865.     gc = top_level_edit_palette->gc;
  866.  
  867.   if (gc)
  868.     palette_entries_update_small_preview (entries, gc);
  869.  
  870.   if ((palette = top_level_palette))
  871.     {
  872.       if (palette->entries == entries)
  873.     {
  874.       palette_dialog_draw_entries (palette,
  875.                        color->position / palette->columns,
  876.                        color->position % palette->columns);
  877.     }
  878.     }
  879.  
  880.   if ((palette = top_level_edit_palette))
  881.     {
  882.       if (palette->entries == entries)
  883.     {
  884.       palette_dialog_draw_entries (palette,
  885.                        color->position / palette->columns,
  886.                        color->position % palette->columns);
  887.     }
  888.     }
  889. }
  890.  
  891. static void
  892. palette_refresh_all (void)
  893. {
  894.   PaletteDialog *palette;
  895.  
  896.   default_palette_entries = NULL;
  897.  
  898.   palettes_free ();
  899.   palettes_init (FALSE);
  900.  
  901.   if ((palette = top_level_palette))
  902.     {
  903.       palette_dialog_clist_refresh (palette);
  904.       palette->columns_valid = FALSE;
  905.       palette_dialog_redraw (palette);
  906.       palette_dialog_clist_scroll_to_current (palette);
  907.     }
  908.  
  909.   if ((palette = top_level_edit_palette))
  910.     {
  911.       palette_dialog_clist_refresh (palette);
  912.       palette->columns_valid = FALSE;
  913.       palette_dialog_redraw (palette);
  914.       palette_dialog_clist_scroll_to_current (palette);
  915.     }
  916.  
  917.   /*  Update other selectors on screen  */
  918.   palette_select_refresh_all ();
  919. }
  920.  
  921. /*  called from color_picker.h  *********************************************/
  922.  
  923. void
  924. palette_set_active_color (gint r,
  925.               gint g,
  926.               gint b,
  927.               gint state)
  928. {
  929.   if (top_level_edit_palette && top_level_edit_palette->entries) 
  930.     {
  931.       switch (state) 
  932.      { 
  933.      case COLOR_NEW: 
  934.       top_level_edit_palette->color =
  935.         palette_entries_add_entry (top_level_edit_palette->entries,
  936.                        _("Untitled"), r, g, b); 
  937.       palette_update_all (top_level_edit_palette->entries);
  938.        break;
  939.  
  940.      case COLOR_UPDATE_NEW: 
  941.        top_level_edit_palette->color->color[0] = r;
  942.        top_level_edit_palette->color->color[1] = g;
  943.        top_level_edit_palette->color->color[2] = b;
  944.       palette_draw_all (top_level_edit_palette->entries,
  945.                 top_level_edit_palette->color);
  946.        break; 
  947.       
  948.      default: 
  949.        break; 
  950.      } 
  951.     } 
  952.   
  953.   if (active_color == FOREGROUND)
  954.     gimp_context_set_foreground (gimp_context_get_user (), r, g, b);
  955.   else if (active_color == BACKGROUND)
  956.     gimp_context_set_background (gimp_context_get_user (), r, g, b);
  957. }
  958.  
  959. /*  called from palette_select.c  ********************************************/
  960.  
  961. void 
  962. palette_select_palette_init (void)
  963. {
  964.   if (top_level_edit_palette == NULL)
  965.     {
  966.       top_level_edit_palette = palette_dialog_new (FALSE);
  967.       dialog_register (top_level_edit_palette->shell);
  968.     }
  969. }
  970.  
  971. void 
  972. palette_create_edit (PaletteEntries *entries)
  973. {
  974.   if (top_level_edit_palette == NULL)
  975.     {
  976.       top_level_edit_palette = palette_dialog_new (FALSE);
  977.       dialog_register (top_level_edit_palette->shell);
  978.  
  979.       gtk_widget_show (top_level_edit_palette->shell);
  980.       palette_dialog_draw_entries (top_level_edit_palette, -1, -1);
  981.     }
  982.   else
  983.     {
  984.       if (! GTK_WIDGET_VISIBLE (top_level_edit_palette->shell))
  985.     {
  986.       gtk_widget_show (top_level_edit_palette->shell);
  987.       palette_dialog_draw_entries (top_level_edit_palette, -1, -1);
  988.     }
  989.       else
  990.     {
  991.       gdk_window_raise (top_level_edit_palette->shell->window);
  992.     }
  993.     }
  994.  
  995.   if (entries != NULL)
  996.     {
  997.       top_level_edit_palette->entries = entries;
  998.       palette_dialog_clist_scroll_to_current (top_level_edit_palette);
  999.     }
  1000. }
  1001.  
  1002. static void
  1003. palette_select_callback (gint                r,
  1004.              gint                g,
  1005.              gint                b,
  1006.              ColorNotebookState  state,
  1007.              void               *data)
  1008. {
  1009.   PaletteDialog *palette;
  1010.   guchar *color;
  1011.   
  1012.   palette = data;
  1013.  
  1014.   if (palette && palette->entries)
  1015.     {
  1016.       switch (state)
  1017.     {
  1018.     case COLOR_NOTEBOOK_UPDATE:
  1019.       break;
  1020.  
  1021.     case COLOR_NOTEBOOK_OK:
  1022.       if (palette->color)
  1023.         {
  1024.           color = palette->color->color;
  1025.  
  1026.           color[0] = r;
  1027.           color[1] = g;
  1028.           color[2] = b;
  1029.  
  1030.           /*  Update either foreground or background colors  */
  1031.           if (active_color == FOREGROUND)
  1032.         gimp_context_set_foreground (gimp_context_get_user (), r, g, b);
  1033.           else if (active_color == BACKGROUND)
  1034.         gimp_context_set_background (gimp_context_get_user (), r, g, b);
  1035.  
  1036.           palette_draw_all (palette->entries, palette->color);
  1037.         }
  1038.  
  1039.       /* Fallthrough */
  1040.     case COLOR_NOTEBOOK_CANCEL:
  1041.       if (palette->color_notebook_active)
  1042.         {
  1043.           color_notebook_hide (palette->color_notebook);
  1044.           palette->color_notebook_active = FALSE;
  1045.         }
  1046.     }
  1047.     }
  1048. }
  1049.  
  1050. /*  the palette dialog popup menu & callbacks  *******************************/
  1051.  
  1052. static void
  1053. palette_dialog_new_entry_callback (GtkWidget *widget,
  1054.                    gpointer   data)
  1055. {
  1056.   PaletteDialog *palette;
  1057.  
  1058.   palette = data;
  1059.  
  1060.   if (palette && palette->entries)
  1061.     {
  1062.       guchar col[3];
  1063.  
  1064.       if (active_color == FOREGROUND)
  1065.     gimp_context_get_foreground (gimp_context_get_user (),
  1066.                      &col[0], &col[1], &col[2]);
  1067.       else if (active_color == BACKGROUND)
  1068.     gimp_context_get_background (gimp_context_get_user (),
  1069.                      &col[0], &col[1], &col[2]);
  1070.  
  1071.       palette->color = palette_entries_add_entry (palette->entries,
  1072.                           _("Untitled"),
  1073.                           col[0], col[1], col[2]);
  1074.  
  1075.       palette_update_all (palette->entries);
  1076.     }
  1077. }
  1078.  
  1079. static void
  1080. palette_dialog_edit_entry_callback (GtkWidget *widget,
  1081.                     gpointer   data)
  1082. {
  1083.   PaletteDialog *palette;
  1084.   guchar *color;
  1085.  
  1086.   palette = data;
  1087.   if (palette && palette->entries && palette->color)
  1088.     {
  1089.       color = palette->color->color;
  1090.  
  1091.       if (!palette->color_notebook)
  1092.     {
  1093.       palette->color_notebook =
  1094.         color_notebook_new (color[0], color[1], color[2],
  1095.                 palette_select_callback, palette,
  1096.                 FALSE);
  1097.       palette->color_notebook_active = TRUE;
  1098.     }
  1099.       else
  1100.     {
  1101.       if (!palette->color_notebook_active)
  1102.         {
  1103.           color_notebook_show (palette->color_notebook);
  1104.           palette->color_notebook_active = TRUE;
  1105.         }
  1106.  
  1107.       color_notebook_set_color (palette->color_notebook,
  1108.                     color[0], color[1], color[2], 1);
  1109.     }
  1110.     }
  1111. }
  1112.  
  1113. static void
  1114. palette_dialog_delete_entry_callback (GtkWidget *widget,
  1115.                       gpointer   data)
  1116. {
  1117.   PaletteEntry *entry;
  1118.   PaletteDialog *palette;
  1119.   GSList *tmp_link;
  1120.   gint pos = 0;
  1121.  
  1122.   palette = data;
  1123.  
  1124.   if (palette && palette->entries && palette->color)
  1125.     {
  1126.       entry = palette->color;
  1127.       palette->entries->colors = g_slist_remove (palette->entries->colors, entry);
  1128.       palette->entries->n_colors--;
  1129.       palette->entries->changed = TRUE;
  1130.  
  1131.       pos = entry->position;
  1132.       palette_entry_free (entry);
  1133.  
  1134.       tmp_link = g_slist_nth (palette->entries->colors, pos);
  1135.  
  1136.       if (tmp_link)
  1137.     {
  1138.       palette->color = tmp_link->data;
  1139.  
  1140.       while (tmp_link)
  1141.         {
  1142.           entry = tmp_link->data;
  1143.           tmp_link = tmp_link->next;
  1144.           entry->position = pos++;
  1145.         }
  1146.     }
  1147.       else
  1148.     {
  1149.       tmp_link = g_slist_nth (palette->entries->colors, pos - 1);
  1150.       if (tmp_link)
  1151.         palette->color = tmp_link->data;
  1152.     }
  1153.  
  1154.       if (palette->entries->n_colors == 0)
  1155.     palette->color =
  1156.       palette_entries_add_entry (palette->entries,
  1157.                      _("Black"), 0, 0, 0);
  1158.  
  1159.       palette_update_all (palette->entries);
  1160.     }
  1161. }
  1162.  
  1163. static void
  1164. palette_dialog_create_popup_menu (PaletteDialog *palette)
  1165. {
  1166.   GtkWidget *menu;
  1167.   GtkWidget *menu_item;
  1168.  
  1169.   palette->popup_menu = menu = gtk_menu_new ();
  1170.  
  1171.   menu_item = gtk_menu_item_new_with_label (_("New"));
  1172.   gtk_menu_append (GTK_MENU (menu), menu_item);
  1173.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate", 
  1174.               GTK_SIGNAL_FUNC (palette_dialog_new_entry_callback),
  1175.               (gpointer) palette);
  1176.   gtk_widget_show (menu_item);
  1177.  
  1178.   menu_item = gtk_menu_item_new_with_label (_("Edit"));
  1179.   gtk_menu_append (GTK_MENU (menu), menu_item);
  1180.  
  1181.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate", 
  1182.               GTK_SIGNAL_FUNC (palette_dialog_edit_entry_callback),
  1183.               (gpointer) palette);
  1184.   gtk_widget_show (menu_item);
  1185.  
  1186.   palette->edit_menu_item = menu_item;
  1187.  
  1188.   menu_item = gtk_menu_item_new_with_label (_("Delete"));
  1189.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate", 
  1190.               GTK_SIGNAL_FUNC (palette_dialog_delete_entry_callback),
  1191.               (gpointer) palette);
  1192.   gtk_menu_append (GTK_MENU (menu), menu_item);
  1193.   gtk_widget_show (menu_item);
  1194.  
  1195.   palette->delete_menu_item = menu_item;
  1196. }
  1197.  
  1198. /*  the color area event callbacks  ******************************************/
  1199.  
  1200. static gint
  1201. palette_dialog_eventbox_button_press (GtkWidget      *widget,
  1202.                       GdkEventButton *bevent,
  1203.                       PaletteDialog  *palette)
  1204. {
  1205.   if (gtk_get_event_widget ((GdkEvent *) bevent) == palette->color_area)
  1206.     return FALSE;
  1207.  
  1208.   if (bevent->button == 3)
  1209.     {
  1210.       if (GTK_WIDGET_SENSITIVE (palette->edit_menu_item))
  1211.     {
  1212.       gtk_widget_set_sensitive (palette->edit_menu_item, FALSE);
  1213.       gtk_widget_set_sensitive (palette->delete_menu_item, FALSE);
  1214.     }
  1215.  
  1216.       gtk_menu_popup (GTK_MENU (palette->popup_menu), NULL, NULL, 
  1217.               NULL, NULL, 3,
  1218.               bevent->time);
  1219.     }
  1220.  
  1221.   return TRUE;
  1222. }
  1223.  
  1224. static gint
  1225. palette_dialog_color_area_events (GtkWidget     *widget,
  1226.                   GdkEvent      *event,
  1227.                   PaletteDialog *palette)
  1228. {
  1229.   GdkEventButton *bevent;
  1230.   GSList *tmp_link;
  1231.   gint r, g, b;
  1232.   gint entry_width;
  1233.   gint entry_height;
  1234.   gint row, col;
  1235.   gint pos;
  1236.  
  1237.   switch (event->type)
  1238.     {
  1239.     case GDK_EXPOSE:
  1240.       palette_dialog_redraw (palette);
  1241.       break;
  1242.  
  1243.     case GDK_BUTTON_PRESS:
  1244.       bevent = (GdkEventButton *) event;
  1245.       entry_width  = palette->col_width + SPACING;
  1246.       entry_height = (ENTRY_HEIGHT * palette->zoom_factor) +  SPACING;
  1247.       col = (bevent->x - 1) / entry_width;
  1248.       row = (bevent->y - 1) / entry_height;
  1249.       pos = row * palette->columns + col;
  1250.       
  1251.       tmp_link = (palette->entries != NULL) ? g_slist_nth (palette->entries->colors, pos) : NULL;
  1252.  
  1253.       if (tmp_link)
  1254.     palette->dnd_color = tmp_link->data;
  1255.       else
  1256.     palette->dnd_color = NULL;
  1257.  
  1258.       if ((bevent->button == 1 || bevent->button == 3) && palette->entries)
  1259.     {
  1260.       if (tmp_link)
  1261.         {
  1262.           if (palette->color)
  1263.         {
  1264.           palette->freeze_update = TRUE;
  1265.            palette_dialog_draw_entries (palette, -1, -1);
  1266.           palette->freeze_update = FALSE;
  1267.         }
  1268.           palette->color = tmp_link->data;
  1269.  
  1270.           /*  Update either foreground or background colors  */
  1271.           r = palette->color->color[0];
  1272.           g = palette->color->color[1];
  1273.           b = palette->color->color[2];
  1274.           if (active_color == FOREGROUND)
  1275.         {
  1276.           if (bevent->state & GDK_CONTROL_MASK)
  1277.             gimp_context_set_background (gimp_context_get_user (),
  1278.                          r, g, b);
  1279.           else
  1280.             gimp_context_set_foreground (gimp_context_get_user (),
  1281.                          r, g, b);
  1282.         }
  1283.           else if (active_color == BACKGROUND)
  1284.         {
  1285.           if (bevent->state & GDK_CONTROL_MASK)
  1286.             gimp_context_set_foreground (gimp_context_get_user (),
  1287.                          r, g, b);
  1288.           else
  1289.             gimp_context_set_background (gimp_context_get_user (),
  1290.                          r, g, b);
  1291.         }
  1292.  
  1293.           palette_dialog_draw_entries (palette, row, col);
  1294.           /*  Update the active color name  */
  1295.           gtk_entry_set_text (GTK_ENTRY (palette->color_name),
  1296.                   palette->color->name);
  1297.           gtk_widget_set_sensitive (palette->color_name, TRUE);
  1298.           /* palette_update_current_entry (palette); */
  1299.  
  1300.           if (bevent->button == 3)
  1301.         {
  1302.           if (! GTK_WIDGET_SENSITIVE (palette->edit_menu_item))
  1303.             {
  1304.               gtk_widget_set_sensitive (palette->edit_menu_item, TRUE);
  1305.               gtk_widget_set_sensitive (palette->delete_menu_item, TRUE);
  1306.             }
  1307.  
  1308.           gtk_menu_popup (GTK_MENU (palette->popup_menu), NULL, NULL, 
  1309.                   NULL, NULL, 3,
  1310.                   bevent->time);
  1311.         }
  1312.         }
  1313.       else
  1314.         {
  1315.           if (bevent->button == 3)
  1316.         {
  1317.           if (GTK_WIDGET_SENSITIVE (palette->edit_menu_item))
  1318.             {
  1319.               gtk_widget_set_sensitive (palette->edit_menu_item, FALSE);
  1320.               gtk_widget_set_sensitive (palette->delete_menu_item, FALSE);
  1321.             }
  1322.  
  1323.           gtk_menu_popup (GTK_MENU (palette->popup_menu), NULL, NULL, 
  1324.                   NULL, NULL, 3,
  1325.                   bevent->time);
  1326.         }
  1327.         }
  1328.     }
  1329.       break;
  1330.  
  1331.     default:
  1332.       break;
  1333.     }
  1334.  
  1335.   return FALSE;
  1336. }
  1337.  
  1338. /*  functions for drawing & updating the palette dialog color area  **********/
  1339.  
  1340. static int
  1341. palette_dialog_draw_color_row (guchar        **colors,
  1342.                    gint            ncolors,
  1343.                    gint            y,
  1344.                    gint            column_highlight,
  1345.                    guchar         *buffer,
  1346.                    PaletteDialog  *palette)
  1347. {
  1348.   guchar *p;
  1349.   guchar bcolor;
  1350.   gint width, height;
  1351.   gint entry_width;
  1352.   gint entry_height;
  1353.   gint vsize;
  1354.   gint vspacing;
  1355.   gint i, j;
  1356.   GtkWidget *preview;
  1357.  
  1358.   if (! palette)
  1359.     return -1;
  1360.  
  1361.   preview = palette->color_area;
  1362.  
  1363.   bcolor = 0;
  1364.  
  1365.   width = preview->requisition.width;
  1366.   height = preview->requisition.height;
  1367.   entry_width = palette->col_width;
  1368.   entry_height = (ENTRY_HEIGHT * palette->zoom_factor);
  1369.  
  1370.   if ((y >= 0) && ((y + SPACING) < height))
  1371.     vspacing = SPACING;
  1372.   else if (y < 0)
  1373.     vspacing = SPACING + y;
  1374.   else
  1375.     vspacing = height - y;
  1376.  
  1377.   if (vspacing > 0)
  1378.     {
  1379.       if (y < 0)
  1380.     y += SPACING - vspacing;
  1381.  
  1382.       for (i = SPACING - vspacing; i < SPACING; i++, y++)
  1383.     {
  1384.       p = buffer;
  1385.       for (j = 0; j < width; j++)
  1386.         {
  1387.           *p++ = bcolor;
  1388.           *p++ = bcolor;
  1389.           *p++ = bcolor;
  1390.         }
  1391.       
  1392.       if (column_highlight >= 0)
  1393.         {
  1394.           guchar *ph = &buffer[3*column_highlight*(entry_width+SPACING)];
  1395.           for (j = 0 ; j <= entry_width + SPACING; j++)
  1396.         {
  1397.           *ph++ = ~bcolor;
  1398.           *ph++ = ~bcolor;
  1399.           *ph++ = ~bcolor;
  1400.         }
  1401.            gtk_preview_draw_row (GTK_PREVIEW (preview), buffer, 0,
  1402.                     y + entry_height + 1, width); 
  1403.         }
  1404.  
  1405.       gtk_preview_draw_row (GTK_PREVIEW (preview), buffer, 0, y, width);
  1406.     }
  1407.  
  1408.       if (y > SPACING)
  1409.     y += SPACING - vspacing;
  1410.     }
  1411.   else
  1412.     y += SPACING;
  1413.  
  1414.   vsize = (y >= 0) ? (entry_height) : (entry_height + y);
  1415.  
  1416.   if ((y >= 0) && ((y + entry_height) < height))
  1417.     vsize = entry_height;
  1418.   else if (y < 0)
  1419.     vsize = entry_height + y;
  1420.   else
  1421.     vsize = height - y;
  1422.  
  1423.   if (vsize > 0)
  1424.     {
  1425.       p = buffer;
  1426.       for (i = 0; i < ncolors; i++)
  1427.     {
  1428.       for (j = 0; j < SPACING; j++)
  1429.         {
  1430.           *p++ = bcolor;
  1431.           *p++ = bcolor;
  1432.           *p++ = bcolor;
  1433.         }
  1434.  
  1435.       for (j = 0; j < entry_width; j++)
  1436.         {
  1437.           *p++ = colors[i][0];
  1438.           *p++ = colors[i][1];
  1439.           *p++ = colors[i][2];
  1440.         }
  1441.     }
  1442.  
  1443.       for (i = 0; i < (palette->columns - ncolors); i++)
  1444.     {
  1445.       for (j = 0; j < (SPACING + entry_width); j++)
  1446.         {
  1447.           *p++ = 0;
  1448.           *p++ = 0;
  1449.           *p++ = 0;
  1450.         }
  1451.     }
  1452.  
  1453.       for (j = 0; j < SPACING; j++)
  1454.     {
  1455.       if (ncolors == column_highlight)
  1456.         {
  1457.           *p++ = ~bcolor;
  1458.           *p++ = ~bcolor;
  1459.           *p++ = ~bcolor;
  1460.         }
  1461.       else
  1462.         {
  1463.           *p++ = bcolor;
  1464.           *p++ = bcolor;
  1465.           *p++ = bcolor;
  1466.         }
  1467.     }
  1468.  
  1469.       if (y < 0)
  1470.     y += entry_height - vsize;
  1471.       for (i = 0; i < vsize; i++, y++)
  1472.     {
  1473.       if (column_highlight >= 0)
  1474.         {
  1475.           guchar *ph = &buffer[3*column_highlight*(entry_width+SPACING)];
  1476.           *ph++ = ~bcolor;
  1477.           *ph++ = ~bcolor;
  1478.           *ph++ = ~bcolor;
  1479.           ph += 3*(entry_width);
  1480.           *ph++ = ~bcolor;
  1481.           *ph++ = ~bcolor;
  1482.           *ph++ = ~bcolor;
  1483.         }
  1484.       gtk_preview_draw_row (GTK_PREVIEW (preview), buffer, 0, y, width);
  1485.     }
  1486.       if (y > entry_height)
  1487.     y += entry_height - vsize;
  1488.     }
  1489.   else
  1490.     y += entry_height;
  1491.  
  1492.   return y;
  1493. }
  1494.  
  1495. static void
  1496. palette_dialog_draw_entries (PaletteDialog *palette,
  1497.                  gint           row_start,
  1498.                  gint           column_highlight)
  1499. {
  1500.   PaletteEntry *entry;
  1501.   guchar *buffer;
  1502.   guchar **colors;
  1503.   GSList *tmp_link;
  1504.   gint width, height;
  1505.   gint entry_width;
  1506.   gint entry_height;
  1507.   gint index, y;
  1508.  
  1509.   if (palette && palette->entries)
  1510.     {
  1511.       width  = palette->color_area->requisition.width;
  1512.       height = palette->color_area->requisition.height;
  1513.  
  1514.       entry_width  = palette->col_width;
  1515.       entry_height = (ENTRY_HEIGHT * palette->zoom_factor);
  1516.  
  1517.       if (entry_width <= 0) return;
  1518.  
  1519.       colors = g_malloc (sizeof (guchar *) * palette->columns * 3);
  1520.       buffer = g_malloc (width * 3);
  1521.  
  1522.       if (row_start < 0)
  1523.     {
  1524.       y = 0;
  1525.       tmp_link = palette->entries->colors;
  1526.       column_highlight = -1;
  1527.     }
  1528.       else
  1529.     {
  1530.       y = (entry_height + SPACING) * row_start;
  1531.       tmp_link = g_slist_nth (palette->entries->colors,
  1532.                   row_start * palette->columns);
  1533.     }
  1534.       index = 0;
  1535.  
  1536.       while (tmp_link)
  1537.     {
  1538.       entry = tmp_link->data;
  1539.       tmp_link = tmp_link->next;
  1540.  
  1541.       colors[index] = entry->color;
  1542.       index++;
  1543.  
  1544.       if (index == palette->columns)
  1545.         {
  1546.           index = 0;
  1547.           y = palette_dialog_draw_color_row (colors, palette->columns, y,
  1548.                          column_highlight, buffer,
  1549.                          palette);
  1550.           if (y >= height || row_start >= 0)
  1551.         {
  1552.           /* This row only */
  1553.           gtk_widget_draw (palette->color_area, NULL);
  1554.           g_free (buffer);
  1555.           g_free (colors);
  1556.           return;
  1557.         }
  1558.         }
  1559.     }
  1560.  
  1561.       while (y < height)
  1562.     {
  1563.       y = palette_dialog_draw_color_row (colors, index, y, column_highlight,
  1564.                          buffer, palette);
  1565.       index = 0;
  1566.           if (row_start >= 0)
  1567.         break;
  1568.     }
  1569.  
  1570.       g_free (buffer);
  1571.       g_free (colors);
  1572.  
  1573.       if (palette->freeze_update == FALSE)
  1574.     gtk_widget_draw (palette->color_area, NULL);
  1575.     }
  1576. }
  1577.  
  1578. static void
  1579. palette_dialog_scroll_top_left (PaletteDialog *palette)
  1580. {
  1581.   GtkAdjustment *hadj;
  1582.   GtkAdjustment *vadj;
  1583.  
  1584.   /*  scroll viewport to top left  */
  1585.   if (palette && palette->scrolled_window)
  1586.     {
  1587.       hadj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (palette->scrolled_window));
  1588.       vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (palette->scrolled_window));
  1589.  
  1590.       if (hadj)
  1591.     gtk_adjustment_set_value (hadj, 0.0);
  1592.       if (vadj)
  1593.     gtk_adjustment_set_value (vadj, 0.0);
  1594.     }
  1595. }
  1596.  
  1597. static void
  1598. palette_dialog_redraw (PaletteDialog *palette)
  1599. {
  1600.   GtkWidget *parent;
  1601.   gint vsize;
  1602.   gint nrows;
  1603.   gint n_entries;
  1604.   gint preview_width;
  1605.   guint width;
  1606.  
  1607.   if (!palette->entries)
  1608.     return;
  1609.  
  1610.   width = palette->color_area->parent->parent->parent->allocation.width;
  1611.  
  1612.   if ((palette->columns_valid) && palette->last_width == width)
  1613.     return;
  1614.  
  1615.   palette->last_width = width;
  1616.   palette->col_width = width / (palette->columns + 1) - SPACING;
  1617.   if (palette->col_width < 0) palette->col_width = 0;
  1618.   palette->columns_valid = TRUE;
  1619.  
  1620.   n_entries = palette->entries->n_colors;
  1621.   nrows = n_entries / palette->columns;
  1622.   if (n_entries % palette->columns)
  1623.     nrows += 1;
  1624.  
  1625.   vsize = nrows * (SPACING + (gint) (ENTRY_HEIGHT * palette->zoom_factor)) + SPACING;
  1626.  
  1627.   parent = palette->color_area->parent->parent;
  1628.   gtk_widget_ref (palette->color_area->parent);
  1629.   gtk_container_remove (GTK_CONTAINER (parent), palette->color_area->parent);
  1630.  
  1631.   preview_width = (palette->col_width + SPACING) * palette->columns + SPACING;
  1632.  
  1633.   gtk_preview_size (GTK_PREVIEW (palette->color_area), preview_width, vsize);
  1634.  
  1635.   gtk_container_add (GTK_CONTAINER (parent), palette->color_area->parent);
  1636.   gtk_widget_unref (palette->color_area->parent);
  1637.  
  1638.   palette_dialog_draw_entries (palette, -1, -1);
  1639. }
  1640.  
  1641. /*  the palette dialog clist "select_row" callback  **************************/
  1642.  
  1643. static void
  1644. palette_dialog_list_item_update (GtkWidget      *widget, 
  1645.                  gint            row,
  1646.                  gint            column,
  1647.                  GdkEventButton *event,
  1648.                  gpointer        data)
  1649. {
  1650.   PaletteDialog *palette;
  1651.   PaletteEntries *p_entries;
  1652.  
  1653.   palette = (PaletteDialog *) data;
  1654.  
  1655.   if (palette->color_notebook_active)
  1656.     {
  1657.       color_notebook_hide (palette->color_notebook);
  1658.       palette->color_notebook_active = FALSE;
  1659.     }
  1660.  
  1661.   if (palette->color_notebook)
  1662.     color_notebook_free (palette->color_notebook);
  1663.   palette->color_notebook = NULL;
  1664.  
  1665.   p_entries = 
  1666.     (PaletteEntries *) gtk_clist_get_row_data (GTK_CLIST (palette->clist), row);
  1667.  
  1668.   palette->entries = p_entries;
  1669.   palette->columns_valid = FALSE;
  1670.  
  1671.   palette_dialog_redraw (palette);
  1672.   palette_dialog_scroll_top_left (palette);
  1673.  
  1674.   /*  Stop errors in case no colors are selected  */ 
  1675.   gtk_signal_handler_block (GTK_OBJECT (palette->color_name),
  1676.                 palette->entry_sig_id);
  1677.   gtk_entry_set_text (GTK_ENTRY (palette->color_name), _("Undefined")); 
  1678.   gtk_widget_set_sensitive (palette->color_name, FALSE);
  1679.   gtk_signal_handler_unblock (GTK_OBJECT (palette->color_name),
  1680.                   palette->entry_sig_id);
  1681. }
  1682.  
  1683. /*  the color name entry callback  *******************************************/
  1684.  
  1685. static void
  1686. palette_dialog_color_name_entry_changed (GtkWidget *widget,
  1687.                      gpointer   data)
  1688. {
  1689.   PaletteDialog *palette;
  1690.  
  1691.   palette = data;
  1692.   g_return_if_fail (palette->entries != NULL);
  1693.  
  1694.   if (palette->color->name)
  1695.     g_free (palette->color->name);
  1696.   palette->color->name = 
  1697.     g_strdup (gtk_entry_get_text (GTK_ENTRY (palette->color_name)));
  1698.  
  1699.   palette->entries->changed = TRUE;
  1700. }
  1701.  
  1702. /*  palette zoom functions & callbacks  **************************************/
  1703.  
  1704. static void
  1705. palette_dialog_redraw_zoom (PaletteDialog *palette)
  1706. {
  1707.   if (palette->zoom_factor > 4.0)
  1708.     {
  1709.       palette->zoom_factor = 4.0;
  1710.     }
  1711.   else if (palette->zoom_factor < 0.1)
  1712.     {
  1713.       palette->zoom_factor = 0.1;
  1714.     }
  1715.   
  1716.   palette->columns = COLUMNS;
  1717.   palette->columns_valid = FALSE;
  1718.   palette_dialog_redraw (palette); 
  1719.  
  1720.   palette_dialog_scroll_top_left (palette);
  1721. }
  1722.  
  1723. static void
  1724. palette_dialog_zoomin_callback (GtkWidget *widget,
  1725.                 gpointer   data)
  1726. {
  1727.   PaletteDialog *palette = data;
  1728.  
  1729.   palette->zoom_factor += 0.1;
  1730.   palette_dialog_redraw_zoom (palette);
  1731. }
  1732.  
  1733. static void
  1734. palette_dialog_zoomout_callback (GtkWidget *widget,
  1735.                  gpointer   data)
  1736. {
  1737.   PaletteDialog *palette = data;
  1738.  
  1739.   palette->zoom_factor -= 0.1;
  1740.   palette_dialog_redraw_zoom (palette);
  1741. }
  1742.  
  1743. /*  the palette edit ops callbacks  ******************************************/
  1744.  
  1745. static void
  1746. palette_dialog_add_entries_callback (GtkWidget *widget,
  1747.                      gchar     *palette_name,
  1748.                      gpointer   data)
  1749. {
  1750.   PaletteEntries *entries;
  1751.  
  1752.   entries = palette_entries_new (palette_name);
  1753.  
  1754.   palette_insert_all (entries);
  1755. }
  1756.  
  1757. static void
  1758. palette_dialog_new_callback (GtkWidget *widget,
  1759.                  gpointer   data)
  1760. {
  1761.   GtkWidget *qbox;
  1762.  
  1763.   qbox = gimp_query_string_box (_("New Palette"),
  1764.                 gimp_standard_help_func,
  1765.                 "dialogs/palette_editor/new_palette.html",
  1766.                 _("Enter a name for new palette"),
  1767.                 NULL,
  1768.                 NULL, NULL,
  1769.                 palette_dialog_add_entries_callback, data);
  1770.   gtk_widget_show (qbox);
  1771. }
  1772.  
  1773. static void
  1774. palette_dialog_do_delete_callback (GtkWidget *widget,
  1775.                    gboolean   delete,
  1776.                    gpointer   data)
  1777. {
  1778.   PaletteDialog  *palette;
  1779.   PaletteEntries *entries;
  1780.  
  1781.   palette = (PaletteDialog *) data;
  1782.  
  1783.   gtk_widget_set_sensitive (palette->shell, TRUE);
  1784.  
  1785.   if (!delete)
  1786.     return;
  1787.  
  1788.   if (palette && palette->entries)
  1789.     {
  1790.       entries = palette->entries;
  1791.       if (entries && entries->filename)
  1792.     palette_entries_delete (entries->filename);
  1793.  
  1794.       palette_entries_list = g_slist_remove (palette_entries_list, entries);
  1795.  
  1796.       palette_refresh_all ();
  1797.     }
  1798. }
  1799.  
  1800. static void
  1801. palette_dialog_delete_callback (GtkWidget *widget,
  1802.                 gpointer   data)
  1803. {
  1804.   PaletteDialog *palette;
  1805.  
  1806.   GtkWidget *dialog;
  1807.   gchar     *str;
  1808.  
  1809.   palette = data;
  1810.  
  1811.   if (!palette || !palette->entries)
  1812.     return;
  1813.  
  1814.   gtk_widget_set_sensitive (palette->shell, FALSE);
  1815.  
  1816.   str = g_strdup_printf (_("Are you sure you want to delete\n"
  1817.                            "\"%s\" from the list and from disk?"),
  1818.                          palette->entries->name);
  1819.  
  1820.   dialog = gimp_query_boolean_box (_("Delete Palette"),
  1821.                    gimp_standard_help_func,
  1822.                    "dialogs/palette_editor/delete_palette.html",
  1823.                    FALSE,
  1824.                    str,
  1825.                    _("Delete"), _("Cancel"),
  1826.                    NULL, NULL,
  1827.                    palette_dialog_do_delete_callback,
  1828.                    palette);
  1829.  
  1830.   g_free (str);
  1831.  
  1832.   gtk_widget_show (dialog);
  1833. }
  1834.  
  1835. static void
  1836. palette_dialog_import_callback (GtkWidget *widget,
  1837.                 gpointer   data)
  1838. {
  1839.   if (!import_dialog)
  1840.     {
  1841.       import_dialog = palette_import_dialog_new ((PaletteDialog *) data);
  1842.       gtk_widget_show (import_dialog->dialog);
  1843.     }
  1844.   else
  1845.     {
  1846.       gdk_window_raise (import_dialog->dialog->window);
  1847.     }
  1848. }
  1849.  
  1850. static void
  1851. palette_dialog_merge_entries_callback (GtkWidget *widget,
  1852.                        gchar     *palette_name,
  1853.                        gpointer   data)
  1854. {
  1855.   PaletteDialog  *palette;
  1856.   PaletteEntries *p_entries;
  1857.   PaletteEntries *new_entries;
  1858.   GList          *sel_list;
  1859.  
  1860.   new_entries = palette_entries_new (palette_name);
  1861.  
  1862.   palette = (PaletteDialog *) data;
  1863.  
  1864.   sel_list = GTK_CLIST (palette->clist)->selection;
  1865.  
  1866.   while (sel_list)
  1867.     {
  1868.       gint    row;
  1869.       GSList *cols;
  1870.  
  1871.       row = GPOINTER_TO_INT (sel_list->data);
  1872.       p_entries = 
  1873.     (PaletteEntries *) gtk_clist_get_row_data (GTK_CLIST (palette->clist), row);
  1874.  
  1875.       /* Go through each palette and merge the colors */
  1876.       cols = p_entries->colors;
  1877.       while (cols)
  1878.     {
  1879.       PaletteEntry *entry = cols->data;
  1880.       palette_entries_add_entry (new_entries,
  1881.                      entry->name,
  1882.                      entry->color[0],
  1883.                      entry->color[1],
  1884.                      entry->color[2]);
  1885.       cols = cols->next;
  1886.     }
  1887.       sel_list = sel_list->next;
  1888.     }
  1889.  
  1890.   palette_insert_all (new_entries);
  1891. }
  1892.  
  1893. static void
  1894. palette_dialog_merge_callback (GtkWidget *widget,
  1895.                    gpointer   data)
  1896. {
  1897.   GtkWidget *qbox;
  1898.  
  1899.   qbox = gimp_query_string_box (_("Merge Palette"),
  1900.                 gimp_standard_help_func,
  1901.                 "dialogs/palette_editor/merge_palette.html",
  1902.                 _("Enter a name for merged palette"),
  1903.                 NULL,
  1904.                 NULL, NULL,
  1905.                 palette_dialog_merge_entries_callback,
  1906.                 data);
  1907.   gtk_widget_show (qbox);
  1908. }
  1909.  
  1910. /*  the palette & palette edit action area callbacks  ************************/
  1911.  
  1912. static void
  1913. palette_dialog_save_callback (GtkWidget *widget,
  1914.                   gpointer   data)
  1915. {
  1916.   palette_save_palettes ();
  1917. }
  1918.  
  1919. static void
  1920. palette_dialog_refresh_callback (GtkWidget *widget,
  1921.                  gpointer   data)
  1922. {
  1923.   palette_refresh_all ();
  1924. }
  1925.  
  1926. static void
  1927. palette_dialog_edit_callback (GtkWidget *widget,
  1928.                   gpointer   data)
  1929. {
  1930.   PaletteEntries *p_entries = NULL;
  1931.   PaletteDialog *palette;
  1932.   GList *sel_list;
  1933.  
  1934.   palette = (PaletteDialog *) data;
  1935.   sel_list = GTK_CLIST (palette->clist)->selection;
  1936.  
  1937.   if (sel_list)
  1938.     {
  1939.       p_entries = 
  1940.     (PaletteEntries *) gtk_clist_get_row_data (GTK_CLIST (palette->clist),
  1941.                            GPOINTER_TO_INT (sel_list->data));
  1942.     }
  1943.  
  1944.   palette_create_edit (p_entries);
  1945. }
  1946.  
  1947. static void
  1948. palette_dialog_close_callback (GtkWidget *widget,
  1949.                    gpointer   data)
  1950. {
  1951.   PaletteDialog *palette;
  1952.  
  1953.   palette = data;
  1954.  
  1955.   if (palette)
  1956.     {
  1957.       if (palette->color_notebook_active)
  1958.     {
  1959.       color_notebook_hide (palette->color_notebook);
  1960.       palette->color_notebook_active = FALSE;
  1961.     }
  1962.  
  1963.       if (palette == top_level_edit_palette && import_dialog)
  1964.     {
  1965.       gtk_widget_destroy (import_dialog->dialog);
  1966.       g_free (import_dialog);
  1967.       import_dialog = NULL;
  1968.     }
  1969.       
  1970.       if (GTK_WIDGET_VISIBLE (palette->shell))
  1971.     gtk_widget_hide (palette->shell);
  1972.     }
  1973. }
  1974.  
  1975. /*  the palette dialog color dnd callbacks  **********************************/
  1976.  
  1977. static void
  1978. palette_dialog_drag_color (GtkWidget *widget,
  1979.                guchar    *r,
  1980.                guchar    *g,
  1981.                guchar    *b,
  1982.                gpointer   data)
  1983. {
  1984.   PaletteDialog *palette;
  1985.  
  1986.   palette = (PaletteDialog *) data;
  1987.  
  1988.   if (palette && palette->entries && palette->dnd_color)
  1989.     {
  1990.       *r = (guchar) palette->dnd_color->color[0];
  1991.       *g = (guchar) palette->dnd_color->color[1];
  1992.       *b = (guchar) palette->dnd_color->color[2];
  1993.     }
  1994.   else
  1995.     {
  1996.       *r = *g = *b = 0;
  1997.     }
  1998. }
  1999.  
  2000. static void
  2001. palette_dialog_drop_color (GtkWidget *widget,
  2002.                guchar      r,
  2003.                guchar      g,
  2004.                guchar      b,
  2005.                gpointer    data)
  2006. {
  2007.   PaletteDialog *palette;
  2008.  
  2009.   palette = (PaletteDialog *) data;
  2010.  
  2011.   if (palette && palette->entries)
  2012.     {
  2013.       palette->color =
  2014.     palette_entries_add_entry (palette->entries, _("Untitled"), r, g, b);
  2015.  
  2016.       palette_update_all (palette->entries);
  2017.     }
  2018. }
  2019.  
  2020. /*  the palette & palette edit dialog constructor  ***************************/
  2021.  
  2022. PaletteDialog *
  2023. palette_dialog_new (gboolean editor)
  2024. {
  2025.   PaletteDialog *palette;
  2026.   GtkWidget *hbox;
  2027.   GtkWidget *hbox2;
  2028.   GtkWidget *vbox;
  2029.   GtkWidget *scrolledwindow;
  2030.   GtkWidget *palette_region;
  2031.   GtkWidget *entry;
  2032.   GtkWidget *eventbox;
  2033.   GtkWidget *alignment;
  2034.   GtkWidget *frame;
  2035.   GtkWidget *button;
  2036.   gchar     *titles[3];
  2037.  
  2038.   palette = g_new0 (PaletteDialog, 1);
  2039.   palette->entries               = default_palette_entries;
  2040.   palette->zoom_factor           = 1.0;
  2041.   palette->columns               = COLUMNS;
  2042.   palette->columns_valid         = TRUE;
  2043.   palette->freeze_update         = FALSE;
  2044.  
  2045.   if (!editor)
  2046.     {
  2047.       palette->shell =
  2048.     gimp_dialog_new (_("Color Palette Edit"), "color_palette_edit",
  2049.              gimp_standard_help_func,
  2050.              "dialogs/palette_editor/palette_editor.html",
  2051.              GTK_WIN_POS_NONE,
  2052.              FALSE, TRUE, FALSE,
  2053.  
  2054.              _("Save"), palette_dialog_save_callback,
  2055.              palette, NULL, NULL, FALSE, FALSE,
  2056.              _("Refresh"), palette_dialog_refresh_callback,
  2057.              palette, NULL, NULL, FALSE, FALSE,
  2058.              _("Close"), palette_dialog_close_callback,
  2059.              palette, NULL, NULL, TRUE, TRUE,
  2060.  
  2061.              NULL);
  2062.     }
  2063.   else
  2064.     {
  2065.       palette->shell =
  2066.     gimp_dialog_new (_("Color Palette"), "color_palette",
  2067.              gimp_standard_help_func,
  2068.              "dialogs/palette_selection.html",
  2069.              GTK_WIN_POS_NONE,
  2070.              FALSE, TRUE, FALSE,
  2071.  
  2072.              _("Edit"), palette_dialog_edit_callback,
  2073.              palette, NULL, NULL, FALSE, FALSE,
  2074.              _("Close"), palette_dialog_close_callback,
  2075.              palette, NULL, NULL, TRUE, TRUE,
  2076.  
  2077.              NULL);
  2078.      }
  2079.  
  2080.   /*  The main container widget  */
  2081.   if (editor)
  2082.     {
  2083.       hbox = gtk_notebook_new ();
  2084.       gtk_container_set_border_width (GTK_CONTAINER (hbox), 1);
  2085.     }
  2086.   else
  2087.     {
  2088.       hbox = gtk_hbox_new (FALSE, 4);
  2089.       gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  2090.     }
  2091.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (palette->shell)->vbox), hbox);
  2092.   gtk_widget_show (hbox);
  2093.  
  2094.   vbox = gtk_vbox_new (FALSE, 2);
  2095.   gtk_widget_show (vbox);
  2096.  
  2097.   palette->scrolled_window =
  2098.     scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
  2099.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
  2100.                   GTK_POLICY_AUTOMATIC,
  2101.                   GTK_POLICY_ALWAYS);
  2102.   gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
  2103.   gtk_widget_show (scrolledwindow);
  2104.  
  2105.   eventbox = gtk_event_box_new ();
  2106.   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolledwindow),
  2107.                      eventbox);
  2108.   gtk_signal_connect (GTK_OBJECT (eventbox), "button_press_event",
  2109.               GTK_SIGNAL_FUNC (palette_dialog_eventbox_button_press),
  2110.               palette);
  2111.   gtk_widget_show (eventbox);
  2112.  
  2113.   alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); 
  2114.   gtk_container_add (GTK_CONTAINER (eventbox), alignment);
  2115.   gtk_widget_show (alignment);
  2116.  
  2117.   palette->color_area = palette_region = gtk_preview_new (GTK_PREVIEW_COLOR);
  2118.   gtk_preview_set_dither (GTK_PREVIEW (palette->color_area),
  2119.               GDK_RGB_DITHER_MAX);
  2120.   gtk_preview_size (GTK_PREVIEW (palette_region), PREVIEW_WIDTH, PREVIEW_HEIGHT);
  2121.   
  2122.   gtk_widget_set_events (palette_region, PALETTE_EVENT_MASK);
  2123.   gtk_signal_connect (GTK_OBJECT (palette->color_area), "event",
  2124.               GTK_SIGNAL_FUNC (palette_dialog_color_area_events),
  2125.               palette);
  2126.  
  2127.   gtk_container_add (GTK_CONTAINER (alignment), palette_region);
  2128.   gtk_widget_show (palette_region);
  2129.  
  2130.   /*  dnd stuff  */
  2131.   gtk_drag_source_set (palette_region,
  2132.                        GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
  2133.                        color_palette_target_table, n_color_palette_targets,
  2134.                        GDK_ACTION_COPY | GDK_ACTION_MOVE);
  2135.   gimp_dnd_color_source_set (palette_region, palette_dialog_drag_color, palette);
  2136.  
  2137.   gtk_drag_dest_set (alignment,
  2138.                      GTK_DEST_DEFAULT_HIGHLIGHT |
  2139.                      GTK_DEST_DEFAULT_MOTION |
  2140.                      GTK_DEST_DEFAULT_DROP,
  2141.                      color_palette_target_table, n_color_palette_targets,
  2142.                      GDK_ACTION_COPY);
  2143.   gimp_dnd_color_dest_set (alignment, palette_dialog_drop_color, palette);
  2144.  
  2145.   /*  The color name entry  */
  2146.   hbox2 = gtk_hbox_new (FALSE, 2);
  2147.   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
  2148.   gtk_widget_show (hbox2);
  2149.  
  2150.   entry = palette->color_name = gtk_entry_new ();
  2151.   gtk_widget_show (entry);
  2152.   gtk_box_pack_start (GTK_BOX (hbox2), entry, TRUE, TRUE, 0);
  2153.   gtk_entry_set_text (GTK_ENTRY (entry), _("Undefined"));
  2154.   gtk_widget_set_sensitive (entry, FALSE);
  2155.   palette->entry_sig_id =
  2156.     gtk_signal_connect (GTK_OBJECT (entry), "changed",
  2157.             GTK_SIGNAL_FUNC (palette_dialog_color_name_entry_changed),
  2158.             palette);
  2159.  
  2160.   /*  + and - buttons  */
  2161.   button = gimp_pixmap_button_new (zoom_in_xpm, NULL);
  2162.   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
  2163.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2164.               GTK_SIGNAL_FUNC (palette_dialog_zoomin_callback),
  2165.               (gpointer) palette);
  2166.   gtk_widget_show (button);
  2167.  
  2168.   button = gimp_pixmap_button_new (zoom_out_xpm, NULL);
  2169.   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
  2170.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2171.               GTK_SIGNAL_FUNC (palette_dialog_zoomout_callback),
  2172.               (gpointer) palette);
  2173.   gtk_widget_show (button);
  2174.   
  2175.   /*  clist preview of palettes  */
  2176.   scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
  2177.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
  2178.                   GTK_POLICY_AUTOMATIC,
  2179.                   GTK_POLICY_ALWAYS);
  2180.  
  2181.   if (editor)
  2182.     {
  2183.       gtk_notebook_append_page (GTK_NOTEBOOK (hbox), vbox,
  2184.                 gtk_label_new (_("Palette")));
  2185.       gtk_notebook_append_page (GTK_NOTEBOOK (hbox), scrolledwindow,
  2186.                 gtk_label_new (_("Select")));
  2187.     }
  2188.   else
  2189.     {
  2190.       gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
  2191.       gtk_box_pack_start (GTK_BOX (hbox), scrolledwindow, TRUE, TRUE, 0);
  2192.     }
  2193.  
  2194.   gtk_widget_show (scrolledwindow);
  2195.  
  2196.   titles[0] = _("Palette");
  2197.   titles[1] = _("Ncols");
  2198.   titles[2] = _("Name");
  2199.   palette->clist = gtk_clist_new_with_titles (3, titles);
  2200.   gtk_widget_set_usize (palette->clist, 203, 203);
  2201.   gtk_clist_set_row_height (GTK_CLIST (palette->clist), SM_PREVIEW_HEIGHT + 2);
  2202.   gtk_clist_set_column_width (GTK_CLIST (palette->clist), 0, SM_PREVIEW_WIDTH+2);
  2203.   gtk_clist_column_titles_passive (GTK_CLIST (palette->clist));
  2204.   gtk_container_add (GTK_CONTAINER (scrolledwindow), palette->clist);
  2205.  
  2206.   if (!editor)
  2207.     gtk_clist_set_selection_mode (GTK_CLIST (palette->clist),
  2208.                   GTK_SELECTION_EXTENDED);
  2209.  
  2210.   gtk_signal_connect (GTK_OBJECT (palette->clist), "select_row",
  2211.               GTK_SIGNAL_FUNC (palette_dialog_list_item_update),
  2212.               (gpointer) palette);
  2213.   gtk_widget_show (palette->clist);
  2214.   
  2215.   if (!editor) 
  2216.     {
  2217.       frame = gtk_frame_new (_("Palette Ops"));
  2218.       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
  2219.       gtk_widget_show (frame); 
  2220.  
  2221.       vbox = gtk_vbox_new (FALSE, 2);
  2222.       gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  2223.       gtk_container_add (GTK_CONTAINER (frame), vbox);
  2224.       gtk_widget_show (vbox);
  2225.       
  2226.       button = gtk_button_new_with_label (_("New"));
  2227.       GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  2228.       gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
  2229.       gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2230.               GTK_SIGNAL_FUNC (palette_dialog_new_callback),
  2231.               (gpointer) palette);
  2232.       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  2233.       gimp_help_set_help_data (button, NULL,
  2234.                    "dialogs/palette_editor/new_palette.html");
  2235.       gtk_widget_show (button);
  2236.  
  2237.       button = gtk_button_new_with_label (_("Delete"));
  2238.       GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  2239.       gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
  2240.       gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2241.               GTK_SIGNAL_FUNC (palette_dialog_delete_callback),
  2242.               (gpointer) palette);
  2243.       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  2244.       gimp_help_set_help_data (button, NULL,
  2245.                    "dialogs/palette_editor/delete_palette.html");
  2246.       gtk_widget_show (button);
  2247.       
  2248.       button = gtk_button_new_with_label (_("Import"));
  2249.       GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  2250.       gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
  2251.       gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2252.               GTK_SIGNAL_FUNC (palette_dialog_import_callback),
  2253.               (gpointer) palette);
  2254.       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  2255.       gimp_help_set_help_data (button, NULL,
  2256.                    "dialogs/palette_editor/import_palette.html");
  2257.       gtk_widget_show (button);
  2258.  
  2259.       button = gtk_button_new_with_label (_("Merge"));
  2260.       GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  2261.       gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
  2262.       gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2263.               GTK_SIGNAL_FUNC (palette_dialog_merge_callback),
  2264.               (gpointer) palette);
  2265.       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  2266.       gimp_help_set_help_data (button, NULL,
  2267.                    "dialogs/palette_editor/merge_palette.html");
  2268.       gtk_widget_show (button);
  2269.     }
  2270.  
  2271.   gtk_widget_realize (palette->shell);
  2272.  
  2273.   palette->gc = gdk_gc_new (palette->shell->window);
  2274.  
  2275.   /*  fill the clist  */
  2276.   palette_clist_init (palette->clist, palette->shell, palette->gc);
  2277.   palette_dialog_clist_scroll_to_current (palette);
  2278.  
  2279.   palette_dialog_create_popup_menu (palette);
  2280.  
  2281.   return palette;
  2282. }
  2283.  
  2284. /*****************************************************************************/
  2285. /*  palette import dialog functions  *****************************************/
  2286.  
  2287. /*  functions to create & update the import dialog's gradient selection  *****/
  2288.  
  2289. static void
  2290. palette_import_select_grad_callback (GtkWidget *widget,
  2291.                      gpointer   data)
  2292. {
  2293.   /*  Popup grad edit box ....  */
  2294.   gradient_dialog_create ();
  2295. }
  2296.  
  2297. static void
  2298. palette_import_fill_grad_preview (GtkWidget  *preview,
  2299.                   gradient_t *gradient)
  2300. {
  2301.   guchar buffer[3*IMPORT_PREVIEW_WIDTH];
  2302.   gint loop;
  2303.   guchar *p = buffer;
  2304.   gdouble  dx, cur_x;
  2305.   gdouble  r, g, b, a;
  2306.  
  2307.   dx    = 1.0/ (IMPORT_PREVIEW_WIDTH - 1);
  2308.   cur_x = 0;
  2309.  
  2310.   for (loop = 0 ; loop < IMPORT_PREVIEW_WIDTH; loop++)
  2311.     {
  2312.       gradient_get_color_at (gradient, cur_x, &r, &g, &b, &a);
  2313.       *p++ = r * 255.0;
  2314.       *p++ = g * 255.0;
  2315.       *p++ = b * 255.0;
  2316.       cur_x += dx;
  2317.     }
  2318.  
  2319.   for (loop = 0 ; loop < IMPORT_PREVIEW_HEIGHT; loop++)
  2320.     {
  2321.       gtk_preview_draw_row (GTK_PREVIEW (preview), buffer, 0, loop,
  2322.                 IMPORT_PREVIEW_WIDTH);
  2323.     }
  2324.  
  2325.   gtk_widget_draw (preview, NULL);
  2326. }
  2327.  
  2328. static void
  2329. palette_import_gradient_update (GimpContext *context,
  2330.                 gradient_t  *gradient,
  2331.                 gpointer     data)
  2332. {
  2333.   if (import_dialog && import_dialog->import_type == GRAD_IMPORT)
  2334.     {
  2335.       /* redraw gradient */
  2336.       palette_import_fill_grad_preview (import_dialog->preview, gradient);
  2337.       gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), gradient->name);
  2338.     }
  2339. }
  2340.  
  2341. /*  functions to create & update the import dialog's image selection  ********/
  2342.  
  2343. static void
  2344. palette_import_gimlist_cb (gpointer im,
  2345.                gpointer data)
  2346. {
  2347.   GSList** l;
  2348.  
  2349.   l = (GSList**) data;
  2350.   *l = g_slist_prepend (*l, im);
  2351. }
  2352.  
  2353. static void
  2354. palette_import_gimlist_indexed_cb (gpointer im,
  2355.                    gpointer data)
  2356. {
  2357.   GimpImage *gimage = GIMP_IMAGE (im);
  2358.   GSList** l;
  2359.  
  2360.   if (gimage_base_type (gimage) == INDEXED)
  2361.     {
  2362.       l = (GSList**) data;
  2363.       *l = g_slist_prepend (*l, im);
  2364.     }
  2365. }
  2366.  
  2367. static void
  2368. palette_import_update_image_preview (GimpImage *gimage)
  2369. {
  2370.   TempBuf * preview_buf;
  2371.   gchar *src, *buf;
  2372.   gint x,y,has_alpha;
  2373.   gint sel_width, sel_height;
  2374.   gint pwidth, pheight;
  2375.  
  2376.   import_dialog->gimage = gimage;
  2377.  
  2378.   /* Calculate preview size */
  2379.  
  2380.   sel_width = gimage->width;
  2381.   sel_height = gimage->height;
  2382.  
  2383.   if (sel_width > sel_height) {
  2384.     pwidth  = MIN(sel_width, IMPORT_PREVIEW_WIDTH);
  2385.     pheight = sel_height * pwidth / sel_width;
  2386.   } else {
  2387.     pheight = MIN(sel_height, IMPORT_PREVIEW_HEIGHT);
  2388.     pwidth  = sel_width * pheight / sel_height;
  2389.   }
  2390.   
  2391.   /* Min size is 2 */
  2392.   preview_buf = gimp_image_construct_composite_preview (gimage,
  2393.                             MAX (pwidth, 2),
  2394.                             MAX (pheight, 2));
  2395.  
  2396.   gtk_preview_size (GTK_PREVIEW (import_dialog->preview),
  2397.             preview_buf->width,
  2398.             preview_buf->height);
  2399.  
  2400.   buf = g_new (gchar,  IMPORT_PREVIEW_WIDTH * 3);
  2401.   src = (gchar *) temp_buf_data (preview_buf);
  2402.   has_alpha = (preview_buf->bytes == 2 || preview_buf->bytes == 4);
  2403.   for (y = 0; y <preview_buf->height ; y++)
  2404.     {
  2405.       if (preview_buf->bytes == (1+has_alpha))
  2406.     for (x = 0; x < preview_buf->width; x++)
  2407.       {
  2408.         buf[x*3+0] = src[x];
  2409.         buf[x*3+1] = src[x];
  2410.         buf[x*3+2] = src[x];
  2411.       }
  2412.       else
  2413.     for (x = 0; x < preview_buf->width; x++)
  2414.       {
  2415.         gint stride = 3 + has_alpha;
  2416.         buf[x*3+0] = src[x*stride+0];
  2417.         buf[x*3+1] = src[x*stride+1];
  2418.         buf[x*3+2] = src[x*stride+2];
  2419.       }
  2420.       gtk_preview_draw_row (GTK_PREVIEW (import_dialog->preview),
  2421.                 (guchar *)buf, 0, y, preview_buf->width);
  2422.       src += preview_buf->width * preview_buf->bytes;
  2423.     }
  2424.  
  2425.   g_free (buf);
  2426.   temp_buf_free (preview_buf);
  2427.  
  2428.   gtk_widget_hide (import_dialog->preview);
  2429.   gtk_widget_draw (import_dialog->preview, NULL); 
  2430.   gtk_widget_show (import_dialog->preview);
  2431. }
  2432.  
  2433. static void
  2434. palette_import_image_sel_callback (GtkWidget *widget,
  2435.                    gpointer   data)
  2436. {
  2437.   GimpImage *gimage;
  2438.   gchar *lab;
  2439.  
  2440.   gimage = GIMP_IMAGE (data);
  2441.   palette_import_update_image_preview (gimage);
  2442.  
  2443.   lab = g_strdup_printf ("%s-%d",
  2444.              g_basename (gimage_filename (import_dialog->gimage)),
  2445.              pdb_image_to_id (import_dialog->gimage));
  2446.  
  2447.   gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), lab);
  2448. }
  2449.  
  2450. static void
  2451. palette_import_image_menu_add (GimpImage *gimage)
  2452. {
  2453.   GtkWidget *menuitem;
  2454.   gchar *lab = g_strdup_printf ("%s-%d",
  2455.                 g_basename (gimage_filename (gimage)),
  2456.                 pdb_image_to_id (gimage));
  2457.   menuitem = gtk_menu_item_new_with_label (lab);
  2458.   gtk_widget_show (menuitem);
  2459.   gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
  2460.               GTK_SIGNAL_FUNC (palette_import_image_sel_callback),
  2461.               gimage);
  2462.   gtk_menu_append (GTK_MENU (import_dialog->optionmenu1_menu), menuitem);
  2463. }
  2464.  
  2465. /* Last Param gives us control over what goes in the menu on a delete oper */
  2466. static void
  2467. palette_import_image_menu_activate (gint        redo,
  2468.                     ImportType  type,
  2469.                     GimpImage  *del_image)
  2470. {
  2471.   GSList *list=NULL;
  2472.   gint num_images;
  2473.   GimpImage *last_img = NULL;
  2474.   GimpImage *first_img = NULL;
  2475.   gint act_num = -1;
  2476.   gint count = 0;
  2477.   gchar *lab;
  2478.  
  2479.   if (!import_dialog)
  2480.     return;
  2481.  
  2482.   if (import_dialog->import_type == type && !redo)
  2483.     return;
  2484.  
  2485.   /* Destroy existing widget if necessary */
  2486.   if (import_dialog->image_list)
  2487.     {
  2488.       if (redo) /* Preserve settings in this case */
  2489.         last_img = import_dialog->gimage;
  2490.       gtk_widget_hide (import_dialog->image_list);
  2491.       gtk_widget_destroy (import_dialog->image_list);
  2492.       import_dialog->image_list = NULL;
  2493.     }
  2494.  
  2495.   import_dialog->import_type= type;
  2496.  
  2497.   /* Get list of images */
  2498.   if (import_dialog->import_type == INDEXED_IMPORT)
  2499.     {
  2500.       gimage_foreach (palette_import_gimlist_indexed_cb, &list);
  2501.     }
  2502.   else
  2503.     {
  2504.       gimage_foreach (palette_import_gimlist_cb, &list);
  2505.     }
  2506.  
  2507.   num_images = g_slist_length (list);
  2508.       
  2509.   if (num_images)
  2510.     {
  2511.       gint i;
  2512.       GtkWidget *optionmenu1;
  2513.       GtkWidget *optionmenu1_menu;
  2514.  
  2515.       import_dialog->image_list = optionmenu1 = gtk_option_menu_new ();
  2516.       gtk_widget_set_usize (optionmenu1, IMPORT_PREVIEW_WIDTH, -1);
  2517.       import_dialog->optionmenu1_menu = optionmenu1_menu = gtk_menu_new ();
  2518.  
  2519.       for (i = 0; i < num_images; i++, list = g_slist_next (list))
  2520.         {
  2521.           if (GIMP_IMAGE (list->data) != del_image)
  2522.             {
  2523.           if (first_img == NULL)
  2524.             first_img = GIMP_IMAGE (list->data);
  2525.           palette_import_image_menu_add (GIMP_IMAGE (list->data));
  2526.           if (last_img == GIMP_IMAGE (list->data))
  2527.             act_num = count;
  2528.           else
  2529.             count++;
  2530.         }
  2531.     }
  2532.  
  2533.       gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu1),
  2534.                 optionmenu1_menu);
  2535.       gtk_widget_hide (import_dialog->select);
  2536.       gtk_box_pack_start (GTK_BOX (import_dialog->select_area),
  2537.                       optionmenu1, FALSE, FALSE, 0);
  2538.  
  2539.       if(last_img != NULL && last_img != del_image)
  2540.         palette_import_update_image_preview (last_img);
  2541.       else if (first_img != NULL)
  2542.     palette_import_update_image_preview (first_img);
  2543.  
  2544.       gtk_widget_show (optionmenu1);
  2545.  
  2546.       /* reset to last one */
  2547.       if (redo && act_num >= 0)
  2548.         {
  2549.            gchar *lab = g_strdup_printf ("%s-%d",
  2550.              g_basename (gimage_filename (import_dialog->gimage)),
  2551.              pdb_image_to_id (import_dialog->gimage));
  2552.  
  2553.            gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu1), act_num);
  2554.            gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), lab);
  2555.  
  2556.        g_free (lab);
  2557.     }
  2558.     }
  2559.   g_slist_free (list);
  2560.  
  2561.   lab = g_strdup_printf ("%s-%d",
  2562.              g_basename (gimage_filename (import_dialog->gimage)),
  2563.              pdb_image_to_id (import_dialog->gimage));
  2564.  
  2565.   gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), lab);
  2566.  
  2567.   g_free (lab);
  2568. }
  2569.  
  2570. /*  the import source menu item callbacks  ***********************************/
  2571.  
  2572. static void
  2573. palette_import_grad_callback (GtkWidget *widget,
  2574.                   gpointer   data)
  2575. {
  2576.   if (import_dialog)
  2577.     {
  2578.       gradient_t *gradient;
  2579.  
  2580.       gradient = gimp_context_get_gradient (gimp_context_get_user ());
  2581.  
  2582.       import_dialog->import_type = GRAD_IMPORT;
  2583.       if (import_dialog->image_list)
  2584.     {
  2585.       gtk_widget_hide (import_dialog->image_list);
  2586.       gtk_widget_destroy (import_dialog->image_list);
  2587.       import_dialog->image_list = NULL;
  2588.     }
  2589.       gtk_widget_show (import_dialog->select);
  2590.       palette_import_fill_grad_preview (import_dialog->preview, gradient);
  2591.  
  2592.       gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), gradient->name);
  2593.       gtk_widget_set_sensitive (import_dialog->threshold_scale, FALSE);
  2594.       gtk_widget_set_sensitive (import_dialog->threshold_text, FALSE);
  2595.     }
  2596. }
  2597.  
  2598. static void
  2599. palette_import_image_callback (GtkWidget *widget,
  2600.                    gpointer   data)
  2601. {
  2602.   palette_import_image_menu_activate (FALSE, IMAGE_IMPORT, NULL);
  2603.   gtk_widget_set_sensitive (import_dialog->threshold_scale, TRUE);
  2604.   gtk_widget_set_sensitive (import_dialog->threshold_text, TRUE);
  2605. }
  2606.  
  2607. static void
  2608. palette_import_indexed_callback (GtkWidget *widget,
  2609.                  gpointer   data)
  2610. {
  2611.   palette_import_image_menu_activate (FALSE, INDEXED_IMPORT, NULL);
  2612.   gtk_widget_set_sensitive (import_dialog->threshold_scale, FALSE);
  2613.   gtk_widget_set_sensitive (import_dialog->threshold_text, FALSE);
  2614. }
  2615.  
  2616. /*  functions & callbacks to keep the import dialog uptodate  ****************/
  2617.  
  2618. static gint
  2619. palette_import_image_count (ImportType type)
  2620. {
  2621.   GSList *list=NULL;
  2622.   gint num_images = 0;
  2623.  
  2624.   if (type == INDEXED_IMPORT)
  2625.     {
  2626.       gimage_foreach (palette_import_gimlist_indexed_cb, &list);
  2627.     }
  2628.   else
  2629.     {
  2630.       gimage_foreach (palette_import_gimlist_cb, &list);
  2631.     }
  2632.  
  2633.   num_images = g_slist_length (list);
  2634.  
  2635.   g_slist_free (list);
  2636.  
  2637.   return num_images;
  2638. }
  2639.  
  2640. static void
  2641. palette_import_image_new (GimpSet   *set,
  2642.               GimpImage *gimage,
  2643.               gpointer   data)
  2644. {
  2645.   if (!import_dialog)
  2646.     return;
  2647.  
  2648.   if (!GTK_WIDGET_IS_SENSITIVE (import_dialog->image_menu_item_image))
  2649.     {
  2650.       gtk_widget_set_sensitive (import_dialog->image_menu_item_image, TRUE);
  2651.       return;
  2652.     }
  2653.  
  2654.   if (!GTK_WIDGET_IS_SENSITIVE (import_dialog->image_menu_item_indexed) &&
  2655.       gimage_base_type(gimage) == INDEXED)
  2656.     {
  2657.       gtk_widget_set_sensitive (import_dialog->image_menu_item_indexed, TRUE);
  2658.       return;
  2659.     }
  2660.  
  2661.   /* Now fill in the names if image menu shown */
  2662.   if (import_dialog->import_type == IMAGE_IMPORT ||
  2663.       import_dialog->import_type == INDEXED_IMPORT)
  2664.     {
  2665.       palette_import_image_menu_activate (TRUE, import_dialog->import_type,
  2666.                       NULL);
  2667.     }
  2668. }
  2669.  
  2670. static void
  2671. palette_import_image_destroyed (GimpSet   *set,
  2672.                 GimpImage *gimage,
  2673.                 gpointer   data)
  2674. {
  2675.   if (!import_dialog)
  2676.     return;
  2677.  
  2678.   if (palette_import_image_count (import_dialog->import_type) <= 1)
  2679.     {
  2680.       /* Back to gradient type */
  2681.       gtk_option_menu_set_history (GTK_OPTION_MENU (import_dialog->type_option), 0);
  2682.       palette_import_grad_callback (NULL, NULL);
  2683.       if (import_dialog->image_menu_item_image)
  2684.     gtk_widget_set_sensitive (import_dialog->image_menu_item_image, FALSE);
  2685.       return;
  2686.     }
  2687.  
  2688.   if (import_dialog->import_type == IMAGE_IMPORT ||
  2689.       import_dialog->import_type == INDEXED_IMPORT)
  2690.     {
  2691.       palette_import_image_menu_activate (TRUE, import_dialog->import_type,
  2692.                       gimage);
  2693.     }
  2694. }
  2695.  
  2696. void
  2697. palette_import_image_renamed (GimpImage* gimage)
  2698. {
  2699.   /* Now fill in the names if image menu shown */
  2700.   if (import_dialog && (import_dialog->import_type == IMAGE_IMPORT ||
  2701.       import_dialog->import_type == INDEXED_IMPORT))
  2702.     {
  2703.       palette_import_image_menu_activate (TRUE, import_dialog->import_type,
  2704.                       NULL);
  2705.     }
  2706. }
  2707.  
  2708. /*  create a palette from a gradient  ****************************************/
  2709.  
  2710. static void
  2711. palette_import_create_from_grad (gchar *name)
  2712. {
  2713.   PaletteEntries *entries;
  2714.   gradient_t *gradient;
  2715.  
  2716.   gradient = gimp_context_get_gradient (gimp_context_get_user ());
  2717.  
  2718.   if (gradient)
  2719.     {
  2720.       /* Add names to entry */
  2721.       gdouble  dx, cur_x;
  2722.       gdouble  r, g, b, a;
  2723.  
  2724.       gint sample_sz;
  2725.       gint loop;
  2726.  
  2727.       entries = palette_entries_new (name);
  2728.       sample_sz = (gint) import_dialog->sample->value;  
  2729.  
  2730.       dx    = 1.0 / (sample_sz - 1);
  2731.       cur_x = 0;
  2732.       
  2733.       for (loop = 0; loop < sample_sz; loop++)
  2734.     {
  2735.       gradient_get_color_at (gradient, cur_x, &r, &g, &b, &a);
  2736.       r = r * 255.0;
  2737.       g = g * 255.0;
  2738.       b = b * 255.0;
  2739.       cur_x += dx;
  2740.       palette_entries_add_entry (entries, _("Untitled"),
  2741.                      (gint) r, (gint) g, (gint) b);
  2742.     }
  2743.  
  2744.       palette_insert_all (entries);
  2745.     }
  2746. }
  2747.  
  2748. /*  create a palette from a non-indexed image  *******************************/
  2749.  
  2750. typedef struct _ImgColors ImgColors;
  2751.  
  2752. struct _ImgColors
  2753. {
  2754.   guint count;
  2755.   guint r_adj;
  2756.   guint g_adj;
  2757.   guint b_adj;
  2758.   guchar r;
  2759.   guchar g;
  2760.   guchar b;
  2761. };
  2762.  
  2763. static gint count_color_entries = 0;
  2764.  
  2765. static GHashTable *
  2766. palette_import_store_colors (GHashTable *h_array, 
  2767.                  guchar     *colors,
  2768.                  guchar     *colors_real, 
  2769.                  gint        sample_sz)
  2770. {
  2771.   gpointer found_color = NULL;
  2772.   ImgColors *new_color;
  2773.   guint key_colors = colors[0]*256*256 + colors[1]*256 + colors[2];
  2774.  
  2775.   if(h_array == NULL)
  2776.     {
  2777.       h_array = g_hash_table_new (g_direct_hash, g_direct_equal);
  2778.       count_color_entries = 0;
  2779.     }
  2780.   else
  2781.     {
  2782.       found_color = g_hash_table_lookup (h_array, GUINT_TO_POINTER (key_colors));
  2783.     }
  2784.  
  2785.   if (found_color == NULL)
  2786.     {
  2787.       if (count_color_entries > MAX_IMAGE_COLORS)
  2788.     {
  2789.       /* Don't add any more new ones */
  2790.       return h_array;
  2791.     }
  2792.  
  2793.       count_color_entries++;
  2794.  
  2795.       new_color = g_new (ImgColors, 1);
  2796.  
  2797.       new_color->count = 1;
  2798.       new_color->r_adj = 0;
  2799.       new_color->g_adj = 0;
  2800.       new_color->b_adj = 0;
  2801.       new_color->r = colors[0];
  2802.       new_color->g = colors[1];
  2803.       new_color->b = colors[2];
  2804.  
  2805.       g_hash_table_insert (h_array, GUINT_TO_POINTER (key_colors), new_color);
  2806.     }
  2807.   else
  2808.     {
  2809.       new_color = (ImgColors *) found_color;
  2810.       if(new_color->count < (G_MAXINT - 1))
  2811.     new_color->count++;
  2812.       
  2813.       /* Now do the adjustments ...*/
  2814.       new_color->r_adj += (colors_real[0] - colors[0]);
  2815.       new_color->g_adj += (colors_real[1] - colors[1]);
  2816.       new_color->b_adj += (colors_real[2] - colors[2]);
  2817.  
  2818.       /* Boundary conditions */
  2819.       if(new_color->r_adj > (G_MAXINT - 255))
  2820.     new_color->r_adj /= new_color->count;
  2821.  
  2822.       if(new_color->g_adj > (G_MAXINT - 255))
  2823.     new_color->g_adj /= new_color->count;
  2824.  
  2825.       if(new_color->b_adj > (G_MAXINT - 255))
  2826.     new_color->b_adj /= new_color->count;
  2827.     }
  2828.  
  2829.   return h_array;
  2830. }
  2831.  
  2832. static void
  2833. palette_import_create_sorted_list (gpointer key,
  2834.                    gpointer value,
  2835.                    gpointer user_data)
  2836. {
  2837.   GSList    **sorted_list = (GSList**) user_data;
  2838.   ImgColors  *color_tab  = (ImgColors *) value;
  2839.  
  2840.   *sorted_list = g_slist_prepend (*sorted_list, color_tab);
  2841. }
  2842.  
  2843. static gint
  2844. palette_import_sort_colors (gconstpointer a,
  2845.                 gconstpointer b)
  2846. {
  2847.   ImgColors *s1 = (ImgColors *) a;
  2848.   ImgColors *s2 = (ImgColors *) b;
  2849.  
  2850.   if(s1->count > s2->count)
  2851.     return -1;
  2852.   if(s1->count < s2->count)
  2853.     return 1;
  2854.  
  2855.   return 0;
  2856. }
  2857.  
  2858. static void
  2859. palette_import_create_image_palette (gpointer data,
  2860.                      gpointer user_data)
  2861. {
  2862.   PaletteEntries *entries = (PaletteEntries *) user_data;
  2863.   ImgColors *color_tab = (ImgColors *) data;
  2864.   gint sample_sz;
  2865.   gchar *lab;
  2866.  
  2867.   sample_sz = (gint) import_dialog->sample->value;  
  2868.  
  2869.   if (entries->n_colors >= sample_sz)
  2870.     return;
  2871.  
  2872.   lab = g_strdup_printf ("%s (occurs %u)", _("Untitled"), color_tab->count);
  2873.  
  2874.   /* Adjust the colors to the mean of the the sample */
  2875.   palette_entries_add_entry
  2876.     (entries, lab, 
  2877.      (gint) color_tab->r + (color_tab->r_adj / color_tab->count), 
  2878.      (gint) color_tab->g + (color_tab->g_adj / color_tab->count), 
  2879.      (gint) color_tab->b + (color_tab->b_adj / color_tab->count));
  2880.  
  2881.   g_free (lab);
  2882. }
  2883.  
  2884. static gboolean
  2885. palette_import_color_print_remove (gpointer key,
  2886.                    gpointer value,
  2887.                    gpointer user_data)
  2888. {
  2889.   g_free (value);
  2890.  
  2891.   return TRUE;
  2892. }
  2893.  
  2894. static void
  2895. palette_import_image_make_palette (GHashTable *h_array,
  2896.                    guchar     *name)
  2897. {
  2898.   PaletteEntries *entries;
  2899.   GSList *sorted_list = NULL;
  2900.  
  2901.   g_hash_table_foreach (h_array, palette_import_create_sorted_list,
  2902.             &sorted_list);
  2903.   sorted_list = g_slist_sort (sorted_list, palette_import_sort_colors);
  2904.  
  2905.   entries = palette_entries_new (name);
  2906.   g_slist_foreach (sorted_list, palette_import_create_image_palette, entries);
  2907.  
  2908.   /*  Free up used memory
  2909.    *  Note the same structure is on both the hash list and the sorted
  2910.    *  list. So only delete it once.
  2911.    */
  2912.   g_hash_table_freeze (h_array);
  2913.   g_hash_table_foreach_remove (h_array,
  2914.                    palette_import_color_print_remove, NULL);
  2915.   g_hash_table_thaw (h_array);
  2916.   g_hash_table_destroy (h_array);
  2917.   g_slist_free (sorted_list);
  2918.  
  2919.   palette_insert_all (entries);
  2920. }
  2921.  
  2922. static void
  2923. palette_import_create_from_image (GImage *gimage,
  2924.                   gchar  *pname)
  2925. {
  2926.   PixelRegion imagePR;
  2927.   guchar *image_data;
  2928.   guchar *idata;
  2929.   guchar  rgb[MAX_CHANNELS];
  2930.   guchar  rgb_real[MAX_CHANNELS];
  2931.   gint has_alpha, indexed;
  2932.   gint width, height;
  2933.   gint bytes, alpha;
  2934.   gint i, j;
  2935.   void * pr;
  2936.   gint d_type;
  2937.   GHashTable *store_array = NULL;
  2938.   gint sample_sz;
  2939.   gint threshold = 1;
  2940.  
  2941.   sample_sz = (gint) import_dialog->sample->value;  
  2942.  
  2943.   if (gimage == NULL)
  2944.     return;
  2945.  
  2946.   /*  Get the image information  */
  2947.   bytes = gimage_composite_bytes (gimage);
  2948.   d_type = gimage_composite_type (gimage);
  2949.   has_alpha = (d_type == RGBA_GIMAGE ||
  2950.            d_type == GRAYA_GIMAGE ||
  2951.            d_type == INDEXEDA_GIMAGE);
  2952.   indexed = d_type == INDEXEDA_GIMAGE || d_type == INDEXED_GIMAGE;
  2953.   width = gimage->width;
  2954.   height = gimage->height;
  2955.   pixel_region_init (&imagePR, gimage_composite (gimage), 0, 0,
  2956.              width, height, FALSE);
  2957.  
  2958.   alpha = bytes - 1;
  2959.  
  2960.   threshold = (gint) import_dialog->threshold->value;
  2961.  
  2962.   if(threshold < 1)
  2963.     threshold = 1;
  2964.  
  2965.   /*  iterate over the entire image  */
  2966.   for (pr = pixel_regions_register (1, &imagePR);
  2967.        pr != NULL;
  2968.        pr = pixel_regions_process (pr))
  2969.     {
  2970.       image_data = imagePR.data;
  2971.  
  2972.       for (i = 0; i < imagePR.h; i++)
  2973.     {
  2974.       idata = image_data;
  2975.  
  2976.       for (j = 0; j < imagePR.w; j++)
  2977.         {
  2978.           /*  Get the rgb values for the color  */
  2979.           gimage_get_color (gimage, d_type, rgb, idata);
  2980.           memcpy (rgb_real, rgb, MAX_CHANNELS); /* Structure copy */
  2981.  
  2982.           rgb[0] = (rgb[0] / threshold) * threshold;
  2983.           rgb[1] = (rgb[1] / threshold) * threshold;
  2984.           rgb[2] = (rgb[2] / threshold) * threshold;
  2985.  
  2986.           store_array =
  2987.         palette_import_store_colors (store_array, rgb, rgb_real,
  2988.                          sample_sz);
  2989.  
  2990.           idata += bytes;
  2991.         }
  2992.  
  2993.       image_data += imagePR.rowstride;
  2994.     }
  2995.     }
  2996.  
  2997.   /*  Make palette from the store_array  */
  2998.   palette_import_image_make_palette (store_array, pname);
  2999. }
  3000.  
  3001. /*  create a palette from an indexed image  **********************************/
  3002.  
  3003. static void
  3004. palette_import_create_from_indexed (GImage *gimage,
  3005.                     gchar  *pname)
  3006. {
  3007.   PaletteEntries *entries;
  3008.   gint samples, count;
  3009.  
  3010.   samples = (gint) import_dialog->sample->value;  
  3011.  
  3012.   if (gimage == NULL)
  3013.     return;
  3014.  
  3015.   if (gimage_base_type (gimage) != INDEXED)
  3016.     return;
  3017.  
  3018.   entries = palette_entries_new (pname);
  3019.  
  3020.   for (count= 0; count < samples && count < gimage->num_cols; ++count)
  3021.     {
  3022.       palette_entries_add_entry (entries, NULL,
  3023.                  gimage->cmap[count*3],
  3024.                  gimage->cmap[count*3+1],
  3025.                  gimage->cmap[count*3+2]);
  3026.     }
  3027.  
  3028.   palette_insert_all (entries);
  3029. }
  3030.  
  3031. /*  the palette import action area callbacks  ********************************/
  3032.  
  3033. static void
  3034. palette_import_close_callback (GtkWidget *widget,
  3035.                   gpointer   data)
  3036. {
  3037.   gtk_widget_destroy (import_dialog->dialog);
  3038.   g_free (import_dialog);
  3039.   import_dialog = NULL;
  3040. }
  3041.  
  3042. static void
  3043. palette_import_import_callback (GtkWidget *widget,
  3044.                 gpointer   data)
  3045. {
  3046.   PaletteDialog *palette;
  3047.  
  3048.   palette = data;
  3049.  
  3050.   if (import_dialog)
  3051.     {
  3052.       gchar *pname;
  3053.  
  3054.       pname = gtk_entry_get_text (GTK_ENTRY (import_dialog->entry));
  3055.       if (!pname || !strlen (pname))
  3056.     pname = g_strdup ("tmp");
  3057.       else
  3058.     pname = g_strdup (pname);
  3059.  
  3060.       switch (import_dialog->import_type)
  3061.     {
  3062.     case GRAD_IMPORT:
  3063.       palette_import_create_from_grad (pname);
  3064.       break;
  3065.     case IMAGE_IMPORT:
  3066.       palette_import_create_from_image (import_dialog->gimage, pname);
  3067.       break;
  3068.     case INDEXED_IMPORT:
  3069.       palette_import_create_from_indexed (import_dialog->gimage, pname);
  3070.       break;
  3071.     default:
  3072.       break;
  3073.     }
  3074.       palette_import_close_callback (NULL, NULL);
  3075.     }
  3076. }
  3077.  
  3078. /*  the palette import dialog constructor  ***********************************/
  3079.  
  3080. static ImportDialog *
  3081. palette_import_dialog_new (PaletteDialog *palette)
  3082. {
  3083.   GtkWidget *dialog;
  3084.   GtkWidget *hbox;
  3085.   GtkWidget *frame;
  3086.   GtkWidget *vbox;
  3087.   GtkWidget *table;
  3088.   GtkWidget *label;
  3089.   GtkWidget *spinbutton;
  3090.   GtkWidget *button;
  3091.   GtkWidget *entry;
  3092.   GtkWidget *optionmenu;
  3093.   GtkWidget *optionmenu_menu;
  3094.   GtkWidget *menuitem;
  3095.   GtkWidget *image;
  3096.   GtkWidget *hscale;
  3097.  
  3098.   import_dialog = g_new (ImportDialog, 1);
  3099.   import_dialog->image_list = NULL;
  3100.   import_dialog->gimage     = NULL;
  3101.  
  3102.   import_dialog->dialog = dialog =
  3103.     gimp_dialog_new (_("Import Palette"), "import_palette",
  3104.              gimp_standard_help_func,
  3105.              "dialogs/palette_editor/import_palette.html",
  3106.              GTK_WIN_POS_NONE,
  3107.              FALSE, TRUE, FALSE,
  3108.  
  3109.              _("Import"), palette_import_import_callback,
  3110.              palette, NULL, NULL, FALSE, FALSE,
  3111.              _("Close"), palette_import_close_callback,
  3112.              palette, NULL, NULL, TRUE, TRUE,
  3113.  
  3114.              NULL);
  3115.  
  3116.   /*  The main hbox  */
  3117.   hbox = gtk_hbox_new (FALSE, 4);
  3118.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  3119.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
  3120.   gtk_widget_show (hbox);
  3121.  
  3122.   /*  The "Import" frame  */
  3123.   frame = gtk_frame_new (_("Import"));
  3124.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  3125.   gtk_widget_show (frame);
  3126.  
  3127.   vbox = gtk_vbox_new (FALSE, 2);
  3128.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  3129.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  3130.   gtk_widget_show (vbox);
  3131.  
  3132.   table = gtk_table_new (4, 2, FALSE);
  3133.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
  3134.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  3135.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  3136.   gtk_widget_show (table);
  3137.  
  3138.   /*  The source's name  */
  3139.   label = gtk_label_new (_("Name:"));
  3140.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  3141.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
  3142.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  3143.   gtk_widget_show (label);
  3144.  
  3145.   entry = import_dialog->entry = gtk_entry_new ();
  3146.   gtk_table_attach_defaults (GTK_TABLE (table), entry, 1, 2, 0, 1);
  3147.   {
  3148.     gradient_t* gradient;
  3149.  
  3150.     gradient = gimp_context_get_gradient (gimp_context_get_current ());
  3151.     gtk_entry_set_text (GTK_ENTRY (entry),
  3152.             gradient ? gradient->name : _("new_import"));
  3153.   }
  3154.   gtk_widget_show (entry);
  3155.  
  3156.   /*  The source type  */
  3157.   label = gtk_label_new (_("Source:"));
  3158.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  3159.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
  3160.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  3161.   gtk_widget_show (label);
  3162.  
  3163.   optionmenu = import_dialog->type_option = gtk_option_menu_new ();
  3164.   optionmenu_menu = gtk_menu_new ();
  3165.   gtk_table_attach_defaults (GTK_TABLE (table), optionmenu, 1, 2, 1, 2);
  3166.   menuitem = import_dialog->image_menu_item_gradient = 
  3167.     gtk_menu_item_new_with_label (_("Gradient"));
  3168.   gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
  3169.               GTK_SIGNAL_FUNC (palette_import_grad_callback),
  3170.               NULL);
  3171.   gtk_menu_append (GTK_MENU (optionmenu_menu), menuitem);
  3172.   gtk_widget_show (menuitem);
  3173.  
  3174.   menuitem = import_dialog->image_menu_item_image =
  3175.     gtk_menu_item_new_with_label (_("Image"));
  3176.   gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
  3177.               GTK_SIGNAL_FUNC (palette_import_image_callback),
  3178.               (gpointer) import_dialog);
  3179.   gtk_menu_append (GTK_MENU (optionmenu_menu), menuitem);
  3180.   gtk_widget_show (menuitem);
  3181.   gtk_widget_set_sensitive (menuitem,
  3182.                 palette_import_image_count (IMAGE_IMPORT) > 0);
  3183.  
  3184.   menuitem = import_dialog->image_menu_item_indexed =
  3185.     gtk_menu_item_new_with_label (_("Indexed Palette"));
  3186.   gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
  3187.                       GTK_SIGNAL_FUNC (palette_import_indexed_callback),
  3188.                       (gpointer) import_dialog);
  3189.   gtk_menu_append (GTK_MENU (optionmenu_menu), menuitem);
  3190.   gtk_widget_show (menuitem);
  3191.   gtk_widget_set_sensitive (menuitem,
  3192.                 palette_import_image_count (INDEXED_IMPORT) > 0);
  3193.  
  3194.   gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), optionmenu_menu);
  3195.   gtk_widget_show (optionmenu);
  3196.  
  3197.   /*  The sample size  */
  3198.   label = gtk_label_new (_("Sample Size:"));
  3199.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  3200.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
  3201.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  3202.   gtk_widget_show (label);
  3203.  
  3204.   import_dialog->sample =
  3205.     GTK_ADJUSTMENT(gtk_adjustment_new (256, 2, 10000, 1, 10, 10));
  3206.   spinbutton = gtk_spin_button_new (import_dialog->sample, 1, 0);
  3207.   gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 1, 2, 2, 3);
  3208.   gtk_widget_show (spinbutton);
  3209.  
  3210.   /*  The interval  */
  3211.   label = import_dialog->threshold_text = gtk_label_new (_("Interval:"));
  3212.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  3213.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
  3214.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  3215.   gtk_widget_set_sensitive(label, FALSE);
  3216.   gtk_widget_show (label);
  3217.  
  3218.   import_dialog->threshold = 
  3219.     GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 128, 1, 1, 1));
  3220.   hscale = import_dialog->threshold_scale = 
  3221.     gtk_hscale_new (import_dialog->threshold);
  3222.   gtk_scale_set_value_pos (GTK_SCALE (hscale), GTK_POS_TOP);
  3223.   gtk_scale_set_digits (GTK_SCALE (hscale), 0);
  3224.   gtk_table_attach_defaults (GTK_TABLE (table), hscale, 1, 2, 3, 4);
  3225.   gtk_widget_set_sensitive (hscale, FALSE);
  3226.   gtk_widget_show (hscale);
  3227.  
  3228.   /*  The preview frame  */
  3229.   frame = gtk_frame_new (_("Preview"));
  3230.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  3231.   gtk_widget_show (frame);
  3232.  
  3233.   vbox = import_dialog->select_area = gtk_vbox_new (FALSE, 2);
  3234.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  3235.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  3236.   gtk_widget_show (vbox);
  3237.  
  3238.   image = import_dialog->preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  3239.   gtk_preview_set_dither (GTK_PREVIEW (image), GDK_RGB_DITHER_MAX);
  3240.   gtk_preview_size (GTK_PREVIEW (image),
  3241.             IMPORT_PREVIEW_WIDTH, IMPORT_PREVIEW_HEIGHT);
  3242.   gtk_widget_set_usize (image, IMPORT_PREVIEW_WIDTH, IMPORT_PREVIEW_HEIGHT);
  3243.   gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
  3244.   gtk_widget_show (image);
  3245.  
  3246.   button = import_dialog->select = gtk_button_new_with_label (_("Select"));
  3247.   GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  3248.   gtk_signal_connect (GTK_OBJECT (button), "clicked", 
  3249.               GTK_SIGNAL_FUNC (palette_import_select_grad_callback),
  3250.               (gpointer) image);
  3251.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  3252.   gtk_widget_show (button);
  3253.  
  3254.   /*  Fill with the selected gradient  */
  3255.   palette_import_fill_grad_preview
  3256.     (image, gimp_context_get_gradient (gimp_context_get_user ()));
  3257.   import_dialog->import_type = GRAD_IMPORT;
  3258.   gtk_signal_connect (GTK_OBJECT (gimp_context_get_user ()), "gradient_changed",
  3259.               GTK_SIGNAL_FUNC (palette_import_gradient_update),
  3260.               NULL);
  3261.  
  3262.   /*  keep the dialog up-to-date  */
  3263.   gtk_signal_connect (GTK_OBJECT (image_context), "add",
  3264.               GTK_SIGNAL_FUNC (palette_import_image_new),
  3265.               NULL);
  3266.   gtk_signal_connect (GTK_OBJECT (image_context), "remove",
  3267.               GTK_SIGNAL_FUNC (palette_import_image_destroyed),
  3268.               NULL);
  3269.  
  3270.   return import_dialog;
  3271. }
  3272.